My answer to the question “Should you test private methods” is a resounding YES!
Let me start by giving you two examples.
Imagine that you are writing a Swing table widget that lets you order your columns in several different ways. Your sorting algorithm is private and one day, you introduce a bug in it. If all you do is test the public methods, the widget will simply start showing wrong results and your tests won’t tell you anything more. For all you know, there might be a bug in your Swing code. If you unit test your (private) sorting algorithm, you will catch the error right away instead of wasting time “higher up the stack”.
While this first example is fictitious, this second one is from TestNG itself.
TestNG uses a partial ordering algorithm to determine in what order methods should be invoked. Methods that have no dependent can be invoked at any time but methods that depend on others (or that are depended upon) need to be invoked in a certain order. This requirement creates a “partially ordered set” of methods, which means that some of its elements are ordered but not all.
This algorithm is completely private, but if it goes wrong, TestNG will start failing in very mysterious ways, indicating dependency failures and other strange error messages. It was pretty obvious to me that I needed a separate test for this section of the code.
I am sure that anyone can relate to a similar situation where their code was so dependent on a private section of code that it was vital to make sure that you would know right away if this part should break.
When it comes down to testing, I follow a very simple rule: “if it can break, test it”.
Now that we have determined that there are actually two kinds of testing (private and public), I would actually go one step further and argue the following points:
- Private tests should run before public tests.I don’t think there is much point in running your public tests if some of your private tests are failing. When private tests fail, the entirety of your code might be jeopardized and will probably fail in random places or maybe even pass in places where it should fail. This situation is a little bit like using a compiler that generates invalid code: wouldn’t you try to fix the compiler before you try to compile any program with it?
- Private tests should prevent public tests from running if they fail. This is a consequence of the first point. If your private tests fail, you might as well save yourself the trouble of spending time running your public tests since they will be meaningless.
- Private tests should be listed first in the reports. If some of your private tests fail, they should be the first thing you investigate since fixing them might actually fix the potential failures in your public tests.
Since TestNG supports dependent testing (“don’t bother running test method b() if test method a() didn’t succeed”), it might actually be interesting to add a way to specify that a certain test is testing your private API. This way, TestNG would run it first and make all other non-private tests depend on it…
What do you think?