To test or not to test
I believe in testing, I really do. Combined with continuous integration, daily builds and automation of all aspects of build process, those are for me mandatory elements of a software project which has got any aspiration to be a successful one. Joel thinks there are more.
I believe in unit tests as well as integration and acceptance tests. I can see value of that and I use TDD happily for last two years and unit testing without being so strict about that for much longer time. It just works for me, gives me something.
However I still have questions regarding this subject. Let’s just put up first of them:
Should we or shouldn’t we unit test private methods of a class?
There are valid reasons for both of them. From one hand if we limit ourselves to a public interface and we test our class as a black box which behaves in a certain way and we don’t care how it is implemented then the tests are easier (read cheaper) to maintain. Whenever we have to change implementation we don’t have to change tests. Neat.
But there is other side as well. What about this word unit? What about TDD? If TDD can actively help us with process of developing a single unit of code why not to use that? As we all know the first red - last green routine of writing test, making it fail, developing code, making the test pass might be painful, might take long time to switch to that way of development but and the end of the day gives code of the better quality. But now what shall we do if that single unit of code by design is a private method? Shall we change that following philosophy of design for testability? It again might lead to innocent changes like converting (Java):
private void foo() {
...
}
to:
protected void foo() {
...
}
Then we can create unit tests for that method in the same package. It was really innocent. What if we have to reach to a toolbox with dirty tools? We can’t really use the same solution for C#. Let’s first have a look at the method access modifiers for that language:
- public indicates the method is freely accessible inside and outside of the class in which it is defined
- internal means the method is only accessible to types defined in the same assembly
- protected means the method is accessible in the type in which it is defined, and in derived types of that type. This is used to give derived classes access to the methods in their base class
- protected internal means the method is accessible to types defined in the same assembly or to types in a derived assembly
- private methods are only accessible in the class in which they are defined.
As we can see our dear friends from Microsoft have done it in even more problematic way. We have a choice of converting private methods to internal but our tests have to be placed in the same assembly as the production code or we can use the public modifier or we have to use some tricks with reflection. Not perfect, wrong or smells.
I understand that there is no universal answer for the question above. Applying common sense usually pays off but I wonder what is your opinion about testing in general with focus on testing private methods.
Popularity: 27% [?]

Adrian said,
December 10, 2007 @ 1:21 pm
I think that unit test (certainly inn TDD) should only test the behaviour of the class, i.e. the public or maybe protected methods. You should find that any private methods are implicitly tested anyway, particularly if you’re using TDD.
One irritation I do find however is that, when using Spring, I have to sometimes create protected setter methods to allow the unit tests to inject dependencies or provide mock behaviour.
Probably something I’m doing wrong……
znachor said,
December 10, 2007 @ 2:27 pm
Valid points. Looks like going towards testing public interface is a way forward. However I still have this thought that if we do that that we loose the benefit of test-first approach when we create an unit which is not a part of public interface.
As side note there is pretty interesting debate on InfoQ about Dependency Injection: http://www.infoq.com/news/2007/12/does-di-pay-off
znachor said,
January 7, 2008 @ 12:08 pm
Related article from InfoQ: Private Methods, Test Driven Development, and Good Design: http://www.infoq.com/news/2008/01/private-methods-tdd-design