Uncovered not always bad 12
Let’s say for the sake of argument that you are:
- Using a code coverage tool such as Cobertura, Emma
- You are actually looking at the coverage of your tests (say you’re looking for stale code in our unit tests – [and you’re thinking gosh, I wish I had some unit tests so I could have some unused code in my unit tests])
- You are testing that unit under test generates an exception
In JUnit 4 we might write the following:
@Test(expected=RuntimeException.class)
public void methodThatWeExpectAnException() {
throw new RuntimeException();
}This test will pass. Yes it’s trivial, of course it would pass. (In reality the single line of code would instead send a message to some object that ultimately would need to generate a RuntimeException for a “real” test to pass.) Fine. That’s not the point.
So what’s the problem with this? Nothing, except that some coverage tools will report the last “line” (the close curly-brace) as not being covered since we did not exit the method cleanly.
Here’s a way to rewrite the above test so that you can assure coverage:@Test
public void methodThatWeExpectWillThrowAnException() {
boolean expectedThrown = false;
try {
throw new RuntimeException();
} catch (RuntimeException e) {
expectedThrown = true;
}
assertTrue(expectedThrown);
}This version is a bit longer, isn’t it?
Here are some comments I’d like to hear from you:- Is it any better?
- Does is express our intent any better?
- Isn’t it just silly to run coverage tools on your test code?
- Is anybody having Pascal flashbacks? (If you don’t get this question…you poor &*$^@~).

Flashbacks? Lucky &*$^@~... Pascal is a thing some of us have to deal with on a near-daily basis!
The second version has a lot of syntax that really doesn’t do anything to clarify the intent.
Personally, I prefer the first version, as I’m a big believer in ”’Good’ is good enough.”
The intent of the first test is perfectly clear.
I don’t see the value in making the code bigger just to get a coverage report number higher. To me it would make more sense to spend some time with the coverage report and investigate things that aren’t covered as to why, because as you demonstrated sometimes there’s a good reason.
Interesting to see how wildly out-of-favor comments are these days. You could just add a comment line before the close-brace in the first case, saying, Gee, this isn’t covered, but it’s no big deal... if that kind of thing was the fashion these days.
I would keep the first syntax and get my tests out of the coverage count. Being anal retentive, I hate having uncovered lines in my coverage reports and I don’t personally think it’s important for the tests to be tested for coverage.
Actually, if you don’t buy the anal-retentive argument, there is another good reason to strive for 100% coverage; you don’t waste your time reviewing the same uncovered lines every time (which are “crying wolf…”). You’ll eventually just stop checking and then you won’t notice when new code that really should have coverage is not covered. To me, it’s potentially a slippery slope like starting to not care if a few unit tests are failing.
That’s a great point Dean. We should strive for 100% coverage because then anything that’s not covered is what we should investigate.
Yeah, I wouldn’t tweak the structure of my tests just to increase the coverage in my test code. What does increasing/decreasing/constant test code coverage indicate anyway? Seems just like noise to me.
Now, I will say that I don’t like the JUnit 4 exception syntax because there doesn’t seem to be a way to check what the exception message is (or maybe I just haven’t found it yet)
I’d fix the freakin tool.
;-)
Or rather, I would not warp my code because of the way cobertura, or emma, behaves. I like the first version, and would either fix the tool, or tolerate the coverage miss.
Actually, there’s no way to cover all the production code anyway. Interfaces, for example, aren’t covered by most tools. So there will always be some code that is missed. A few extra closing braces don’t bother me.
I like covering my tests. I have found some very interesting surprises by looking at the portions of my tests that are covered and the portions that are not.
I think fixing the tool is a good way to go. I do think the above fix is way too much. On the other hand I really like covering my tests as well.
I’m under the impression we want to refactor our code. When I hear this, I hear we should do so for both “production” code as well as “test” code. If that’s the case, then I don’t see why we should not cover our tests.
I think you are asking the wrong question. The more interesting seems to be to me: How bad are those code coverage tools??? I think the least they should be able to do is some decent control flow analysis, if not even data flow analysis. If a tool does not report 100% coverage for your three lines example, I would dump it!
While I don’t like coverage filling, I like making assertions on the expected exception message.
Prefer #2, as I usually check the message of the thrown exception: try { throwSomething(); fail(“FooException expected”) } catch (FooException expected) { assertEquals(“Foo”,expected.getMessage()); }