Why Aiming 100 Code Coverage Improves Your Code
My thoughts about aiming for a 100% code coverage in your unit tests.
Created Sep 6, 2015 - Last updated: Sep 6, 2015
On the internet there is a lot of discussion about testing your code for a reasonable 100%. There are some who says that it is a waste of your time, others say that every single line should be tested.
Personally I believe that aiming for a 100% coverage is a good goal to achieve. In my job we’ve decided for our project to go for a 100% coverage with unit tests. This convention already saved us a lot of bugs in our code, because testing every single line of your code forces you to re-think what you’ve made. When writing a test, more then once I’ve refactored my original code to something cleaner and more logical.
Beside cleaner code I encountered another positive thing. Consider the following (pseudo) code:
public function foo() {
if (Foo::Bar === 'expectedResult') {
return 'fooBar is expected!';
}
if (Foo::Bar === 'anotherExpectedResult') {
return 'fooBar has another expected result!';
}
}
When creating unit tests, you write tests that let Foo::Bar
return both expectedResult
and anotherExpectedResult
. But what if, for whatever reason, Foo::Bar
doesn’t return one of those two values? What will you code do? Aiming for 100% coverage forces you to think about it. And here is why (it is pretty simple, really):
If you run the unit tests with coverage, the closing bracket of the second if will never be hit, because in both cases there is already something returned. To get the 100% mark, that line needs also be hit at least once, so you’ve to write a test where Foo::Bar
returns anything except those two values. At this point you have to think about it: is it okay that this function doesn’t return anything? Or has it to return at least something, even if it is false? Or maybe this code is so important, that it has to throw an exception?
I know some code simply can’t be tested. That’s a fact. In my job we’ve come up with this solution: it is allowed to add @codeCoverageIgnore tags to your method (or // @codeCoverageIgnoreStart
and // @codeCoverageIgnoreEnd
if you want to exclude just some lines) but only if you can explain it to a colleague and you’ve a valid reason. It is not the most beautiful solution, but I’ve discovered it works pretty well.
Another small thing about a 100% coverage, albeit personal: I see it more as a challenge to get the coverage to 100% than to, lets say, 95%. If it isn’t already 100%, why should it matter that it is 95%, 94% or 96%?