posted on Saturday, September 18, 2004 9:33 PM
by
anoras
This is why private method testing is good
My coworker Mads Nissen has posted a comment to my post about Visual Studio Team System’s support for private method testing. He discusses private method testing from a test driven development point of view and argues that private method testing has no place in this methodology. He even goes to the extent of stating that private method testing only will be used by inexperienced programmers. I disagree with him on this.
When doing contract-first development and applying test driven methodologies private method testing is not applicable since neither the contract nor the test case describe the inner working of the test target. The built in support in Team System for private method testing wouldn’t even be available in such a scenario since it generates the tests and the proxies to support them based on existing code. When tests are written prior to the target code there is no code to generate tests and proxies from.
The IEEE Standard Computer Dictionary defines unit testing as “Testing of individual hardware or software units or groups of related units”. Since methods within a class rely on other methods within the class or other classes, the interface testing Mads refers to is, from my point of view, testing groups of related units. A unit test usually exercises some particular method in a particular context. Interface or “black box” testing exercises the target in a context where internal methods are interrelated.
You design public methods to be “black boxes” so that the users of a class don’t have to look past the interface to know what the methods do. Having “black box” tests that verify that the public interface functions as intended is a necessity, but in addition you should have “glass box” tests that exercise the individual units within the “black box”. Having knowledge about what is behind the public interface enables you to test the code more thoroughly and gives you a better chance of detecting errors.
If you have a private method used from a public method you should create individual tests for this method. The reason is simple. When basic, low-level code isn’t reliable, the requisite fixes don’t stay at the low level. You fix the low level problem, but that impacts code at higher levels, which then need fixing, and so on. Fixes begin to ripple throughout the code, getting larger and more complicated as they go. Tests ensure that the code is reliable.
In addition testing individual methods reduces the problem scope and makes it easy to write good tests.
The “black box” tests should stick to a class for its entire life time to ensure that the class fulfills its intent. The “glass box” tests should be regarded as technical scaffolding and should be changed with the target code. If a refactoring renders a private method redundant the tests should be refactored to reflect this.
There are some interesting side-effects to testing. One of these is that tests are “executable documentation” of the target’s intended uses. Having a set of tests for the internals of a class make it easy for a maintains-programmer to understand what the code does. Therefore I also disagree that writing tests for private methods reduce the maintainability of the code.
There are many levels of testing and unit tests make up the lowest level. In addition integration tests, acceptance tests, value-chain test and so on must be part of software development projects. Unit tests should test the standalone units. A unit might be a public interface on a class when viewing in the class from the outside or the internals of the class when viewing the class from the inside. There is no conflict between testing the interface and testing the internals, so there is no reason not to do both. With NUnit and other testing tools testing private methods has been very cumbersome and therefore it has seldom been done. Having support for this in Visual Studio Team System is therefore a step in the right direction.