In Java/Junit, I need to test for null with some object. There are a variety of ways I can test a condition but I have been using assertTrue for most of my tests. When I check for nulls in an assertTrue, EclEmma states that it is only testing one branch.
When I resolve the statement into a variable manually (like setting the result to a boolean and passing it into assertTrue) the code coverage is deemed complete on the assert but not on the variable initializing line.
Why is this happening? Is this related to the extra byte code that Java apparently adds as mentioned on http://sourceforge.net/apps/trac/eclemma/wiki/FilteringOptions? Any solutions (besides using other assert statements).
assertTrue:
assertTrue( myObject == null ); //1 of 2 branches
assertTrue:
boolean test = (myObject == null); //1 of 2 branches missing
assertTrue(test); // complete
assertNull:
assertNull( myObject ) //complete;
For most Boolean expressions, the Java compiler generates extra branches in the byte code. JaCoCo produces "branch coverage" based on the generated byte code, not based on the original Java code, and hence shows additional branch coverage information for almost any Boolean expression you would use.
In your code, the Boolean expression you use is myObject == null
.
To compute this value, the Java compiler generates code pushing the two arguments on the stack, and then doing a conditional jump in order to push 1 (true) or 0 (false) on the stack. JaCoCo reports the branch coverage of this conditional jump.
Thus, the fact that you use myObject == null
triggers the behavior you describe.
As some other examples, try this:
boolean t = true;
boolean f = false;
boolean result1 = (t && f) || f; // 3 out of 6 missed.
boolean result2 = !t; // 1 out of 2 missed.
This can be useful if the Boolean expression is, for example, returned by a function, which is used as condition in an if-then-else statement somewhere else. While mostly a consequence of the way the Java compiler works, it helps to assess condition coverage (instead of mere branch coverage) of the original Java code.
This feature isn't too well documented, but here are some pointers:
a = !a
So it is, indeed, related to the extra byte code is generated, but not to the specific examples of synthetic byte compiler constructs for which the filtering options are intended.
NOTE: Did major EDIT since initial answer was too much of a guess. Thanks to @ira-baxter for good & critical discussion.