Posted June 02, 2010.
[ Tdd ]
http://thoughts.karmazilla.net

Only Test The Public API

When programming in Java, I have found that …

Unit tests should only be made agianst the public API. Reliance on package or private scopes for testability is detrimental to the design and leads to fragile tests.

Such is the conclusion that I have recently made. In this context, protected scope is also considered public API, however much one might try to discourage implementation inheritance.

My reasoning goes like this: anything not specified by the public API is an implementation detail. Implementations should be allowed to change, as long as they are correct. Our tests should ensure the correctness of the implementation but not the details of how that correctness is achieved.

If a test relies on implementation details, then that test will likely break when those details change.

What I am beginning to notice is, that when ever I think I need to lift some method or class from private to package-private, I actually have a bit of public API wanting to get out.

It often turns out, that the class that would otherwise have grown something package-private, instead gives birth to an interface and another class that implements that interface.

What this means is that not only do my tests get access to the APIs they want, but so do everybody else who might want to integrate my code (especially important if I’m writing library code).

So, the public API is like a specification and the unit tests ensure that the implementation adheres to that specification. If it cannot be tested through the public API, then it doesn’t matter and can be deleted.

This is another way to achieve high test coverage: just delete any code not covered by a test - according to your tests, it will still work afterwards.

That is, it can generally be deleted. This is only a general rule of thumb and as such there are exceptions. Sometimes checked exceptions force you to write a catch clause that will never execute, and other times you just have write guards against a race condition that is impossible to reproduce on your hardware.

I have run into both of these exceptions. And that “impossible catch clause” you might be wondering about; what are the odds of the UTF-8 character encoding not existing on a system that has Java installed anyway?

That is all.

blog comments powered by Disqus