« Ohmigod - what have I done?!? | Main | Scroll much? »
June 29, 2004
Lies, damn lies and test coverage
Let me start by saying I'm a big fan of automated software development tools. It's a difficult task - most of us need all the help we can get. I use a lot of these tools. I like most of the ones I use. I seek out new ones on occasion. Version control, continuous integration, build management, code duplication checkers, 101 different flavours of testing frameworks, code generation frameworks - I love them all...
However, people can be lulled into a false sense of security with what these tools give us, sometimes to the extent of completely switching their brains to automatic as well, instead of thinking more deeply about what these tools actually give us.
The category of tools which irks me the most in this area are for examining test coverage, the two I've used so far being JCoverage and Clover.
Now don't get me wrong, I think these tools are fabulous things and serve an extremely valuable purpose, but they can give an incorrect (or at least unverifiable) picture of the quality of the test suite. For example, here is a ridiculously simple method and an accompanying test class:
public class TestCoverage {
public static String removeExtension(final String fileName) {
if (fileName == null) {
return null;
}
return fileName.substring(0, fileName.indexOf("."));
}
}
public class TestCoverageTest extends TestCase {
public void testRemoveExtension() {
assertEquals("foobar", TestCoverage.removeExtension("foobar.txt"));
}
public void testRemoveExtensionWithNull() {
assertNull(TestCoverage.removeExtension(null));
}
}
Now, it should be obvious to Blind Freddy that there's an StringIndexOutOfBoundsException just waiting to happen in the method being tested. However, from the perspective of test coverage tools, this method is 100% covered. And when the codebase is of the size and complexity of a typical commerical application, very few missed tests can be seen as easily as this one, even assuming people have the time to trawl through the codebase and test suite in pursuit of such anomalies. And herein lies the problem: test coverage tools (at least the ones I've met) only indicate the quantity of your codebase executed during your test runs, not the quality of the tests themselves. JCoverage and Clover are great at reporting the breadth of a test suite (i.e., what is being tested), but has little to say on the depth or how aspects of the suite. But unfortunately, I hear people frequently mistaking one for the other, leading to statements like:
"Our test suite rocks!!! It's got 85% coverage according to TestCoverPro (tm)(r)(c)"
Well, no - it doesn't (demonstrably) rock. It is demonstrably covered to 85%, but that says nothing of the quality of the test suite, merely the quantity. It may indeed be a high quality suite, but I don't know of any tool that can tell me that automatically. Good test coverage is a necessary, but not sufficient factor of a good test suite. The quality of the suite is a factor of the type of data injected by the tests and the order in which the data/code is executed, not the ratio of tested lines/untested lines.
I'm not trying to say these tools are misleading us, just that people tend to optimize their behaviour for what is rewarded/measured. These tools measure test coverage (i.e., quantity) - leading teams to maximize coverage at the expense of better quality tests.
Bottom line: strive for as high a test coverage figure as you can, but once you've reached that level, don't rest on your laurels. As shown above, 100% tested code can still contain bugs, and every bug found is a red flag marking a missed test.
Test coverage is obviously only part of the story here - other development practices such as test-driven development and pair programming will naturally lead to higher quality tests. Using these sorts of practices in tandem with a thoughtfully chosen set of automated tools will greatly increase the chance of an application that is tested both widely and deeply.
Posted by Andy Marks at June 29, 2004 05:05 PM
Comments
Robert Glass has a good section on test coverage in his "Facts and Fallacies" book. He quite rightly points out that 100% line coverage isn't enough; you haven't validated all the possible inputs, for starters, as you point out.
One advantage, in Java, of checked exceptions in this regard is that because you need to have them handled _somewhere_, you can measure the effectiveness of the handler. Still, that's far from a perfect solution.
The other two aspects to the fallacy of 100% coverage are that you can't test all the combinations, and you can't test the things you left out (particularly requirements that are not filled).
OTH, if I had to pick between two projects, one with 100% test coverage, and the other with 10%, I'd probably rather have the former.
Posted by: Robert Watkins at June 29, 2004 07:41 PM
Post a comment
Thanks for signing in, . Now you can comment. (sign out)
(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)