Monday, February 12, 2007

Testing Private Methods

There are a lot of discussion going on in test infected community on how to go about testing private methods. One of the suggested approach is to nest a static test class within the production class. This package level access static class can be called from our testing class, which in turn would call the private methods.

I strongly disagree with this method. Couple of reasons:

1. We would be adding extra code in the production code.
2. It might add more cost to the customer

First we have to understand that, the reason why we want to test the application is to ensure that our application works well and conforms to certain requirements given by the customer. We need to weigh the cost of maintaining these tests also. Customer pays money for the product, and the testing is the extra burden we are putting on the customer to ensure we deliver something right.

When we deliver the nested class with the production code, we are in fact sending something that was not requested by the customer. This class in turn might introduce its own defect.

Let us take a simple analogy, process of car manufacturing. Consider that the testing team inserts a device into the car during car manufacturing. This device would ensure that they can test "engine temperature" accurately. This device would go with the car to the customer also. Problem here is, we may not know the impact of this device on mileage of the car !!. Even though it has made the lives of developers easy, we are charging the customer for this device too.

I strongly feel that, if we want to test something, we should do so without touching the production code.


Eric said...

Yes, adding an inner class sounds scary, but I do not agree with your analysis. After all, this class is only there to facilitate testing, not to test by itself.

In your analogy, you mention that providing a way to test things in a car is risky. Well... it happens all the time! For any reasonably complex system, there is a way to get deep information on its state, or to test things directly. I hear that car repairmen have exactly this sort of devices for embedded computers. But there is no doubt that the equivalent existed before for cars without computers, whether it has been designed this way from the beginning or not.
Another example: in the servers sold by Sun there was (is?) a way to reach the bios using parallel cables, so even when the network adapter is down, it is possible to configure some things, usually to restart the machine. No doubt that this makes the machines slightly more brittle. But still it was considered a good idea.

To come back to the inner class: would you feel as bad if the private method was made package-friendly? (a friend of mine frequently says that, if your code prevents you from testing easily, change your code)

What about coding using TDD? the method would never have been private to start with.

Anonymous said...

I agree with you about not wanting to ship test code with production code. But static inner test classes can be excluded from the production code since these are compiled into their own .class files. This was an approach used long before junit was in existence.