Cedric is wrong.

Java Add comments

I’m a big fan of Cedric Beust’s work but in “Testing private methods? You bet.” Cedric asserts that private methods should have tests because “if it can break, test it”. In my opinion this is just plain wrong and I believe that Cedrics own examples back me up.

Cedric provides us with a reasonably common scenario.

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

This is variant on a theme that we’ve all come across. In the past I’ve seen people expose private methods as public just to test them and these methods then become a part of the public contract of the class. Funnier is the public method with a note in the javadoc that the method is really private and only exposed for testing purposes. Better yet is the use of reflection to call the a private method to test it. I could go on but I’m guessing you get my point.

My rule is simple. If it’s part of the public contract, test it, if it’s internal implementation, test is via the public contract.

So we now go back to Cedric’s problem. From the description doesn’t this sound like the perfect place to use a strategyy? Cedric’s need for a sorting algorithm sounds like an ideal place for a sorting strategy. You can then test your sorting algorithm simply and easily external to it’s usage in the widget. This breaks the design down neatly but still leaves us with a dangling pointer. The sorting strategy class is now a stand alone class that is not really part of the public contract of the application. We could make the class package protected and have the test in the same package but I like to have my tests in a separate package to ensure that I am just testing the public contract. So following the lead of the eclipse team, I put classes like this, ones that need to be public for implementation purposes but are not a part of the public contract in their own package, internal. Eclipse can even enforce that I don’t directly use classes found in any internal package.

In my opinion Cedric’s solution tests a bad design. No amount of testing will “fix” it. If you need to test a private method look at your design. If the method should be part of the public contract then make it so. If not, take another look at the design of your classes.

2 Responses to “Cedric is wrong.”

  1. R.J. Lorimer Says:

    My only problem with testing private methods is simply that it makes class changes feel *so* brittle; I tried it for a while and felt overwhelmed by the extra amount of time it added to produce tests for all of my internal details - I am guilty of over-modularizing code with lots of private methods on a given object for clarification sometimes, so that may have contributed. I have had better luck sticking with public contracts, as long as they are granular enough that the number of test cases to reach a largely comprehensive state isn’t a stellar number.

    Happy Coding!

    R.J.

  2. Michael Slattery Says:

    I generally agree although I’m don’t have a strong opinion about it. If private methods aren’t being tested directly it’s all the more important that a code coverage tool is used to make sure that all paths of the private method are getting executed.

Leave a Reply

Couldn't find your convert utility. Check that you have ImageMagick installed.