views:

107

answers:

5

Let'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.

+1  A: 

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.

Ngu Soon Hui
The I or Inversion of Control is especially important in decoupling the application for testing. It helps isolate cases and provide an clean place to mock/detect interactions.
smaclell
@smalclell : +1. Nice addon
Ngu Soon Hui
A: 

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.

mattjames
+1  A: 

You might also want to check out these two SO questions:

smaclell
+1  A: 
Adam Liss
+2  A: 

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".

John Deters
do you always use dependency inversion? I use it on a package level only at the moment
f4