Preparing unit tests : What's important to keep in mind when working on a software architecture? [closed]
Want to improve this question? Update the question so it can be answered with facts and cita开发者_运维知识库tions by editing this post.
Closed 5 years ago.
Improve this questionLet's say I'm starting a new project, quality is a top priority.
I plan on doing extensive unit testing, what's important to keep in mind when I'm working on the architecture to ease and empower further unit testing?
edit : I read an article some times ago (I can't find it now) talking about how decoupling instantiation code from classes behaviors could be be helpful when unit testing. That's the kind of design tips I'm seeking here.
Ease of testing comes through being able to replace as many of the dependencies your method has with test code (mocks, fakes, etc.) The currently recommended way to accomplish this is through dependency inversion, aka the Hollywood Principle: "Don't call us, we'll call you." In other words your code should "ask for things, don't look for things."
Once you start thinking this way you'll find code can easily have dependencies on many things. Not only do you have dependencies on other objects, but databases, files, environment variables, OS APIs, globals, singletons, etc. By adhering to a good architecture, you minimize most of these dependencies by providing them via the appropriate layers. So when it comes time to test, you don't need a working database full of test data, you can simply replace the data object with a mock data object.
This also means you have to carefully sort out your object construction from your object execution. The "new" statement placed in a constructor generates a dependency that is very hard to replace with a test mock. It's better to pass those dependencies in via constructor arguments.
Also, keep the Law of Demeter in mind. Don't dig more than one layer deep into an object, or else you create hidden dependencies. Calling Flintstones.Wilma.addChild(pebbles); means what you thought was a dependence on "Flintstones" really is a dependence on both "Flintstones" and "Wilma".
Make sure that your code is testable by making it highly cohesive, lowly decoupled. And make sure you know how to use mocking tools to mock out the dependencies during unit tests.
I recommend you to get familiar with the SOLID principle, so that you can write a more testable code.
You might also want to check out these two SO questions:
- Unit Test Adoption
- What Should Be A Unit
Some random thoughts:
Define your interfaces: decouple the functional modules from each other, and decide how they will communicate with each other. The interface is the “contract” between the developers of different modules. Then, if your tests operate on the interfaces, you're ensuring that the teams can treat each other's modules as black boxes, and therefore work independently.
Build and test at least the basic functionality of the UI first. Once your project can “talk” to you, it can tell you what's working and what's not ... but only if it's not lying to you. (Bonus: if your developers have no choice but to use the UI, you'll quickly identify any shortcomings in ease-of-use, work flow, etc.)
Test at the lowest practical level: the more confident you are that the little pieces work, the easier it will be to combine them into a working whole.
Write at least one test for each feature, based on the specifications, before you start coding. After all, the features are the reason your customers will buy your product. Be sure it's designed to do what it's supposed to do!
Don't be satisfied when it does what it's supposed to do; ensure it doesn't do what it's not supposed to do! Feed it bad data, use it in an illogical way, disconnect the network cable during data transfer, run it alongside conflicting applications. Your customers will.
Good luck!
Your tests will only ever be as good as your requirements. They can be requirements that you come up with up front all at once, they can be requirements that you come up with one at a time as you add features, or they can be requirements that you come up with after you ship it and people start reporting a boat load of bugs, but you can't write a good test if no one can or will document exactly what the thing is supposed to do.
精彩评论