Sonar branch coverage on class declaration
It looks like this is an issue related to the JaCoCo code coverage component of Sonar. JaCoCo works on compiled bytecode rather than Java source, and the Java compiler can produce code which is not directly related to the underlying source.
Looking at the docs for JaCoCo, there's a section which reads (emphasis added):
In some situations it is not obvious, why particular lines do have highlighting or have a particular color. The reason is that the underlying code coverage library JaCoCo works on Java class files only. In some cases the Java compiler creates extra byte code for a particular line of source code. Such situations might be filtered by future versions of JaCoCo/EclEmma.
Following the link in the passage takes you to the FilteringOptions page on the Jacoco's GH site, and it mentions a number of ways in which the JDK can potentially produce code which will will trigger these "spurious" code coverage warnings.
However, that's not what's at play here (or not exactly).
As mentioned JaCoCo works on Java bytecode, so any code which is produced by the compiler that isn't directly attributed to the source will count towards coverage.
In my specific case, I had an assert
which, in the source, represents a branch at the point where the assert happens, but also at a "global" level. If you look at the bytecode for the Foo
class defined above (do a javap -c Foo
), you'll see:
Compiled from "Foo.java"
public class Foo extends java.lang.Object{
static final boolean $assertionsDisabled;
Foo(java.lang.String);
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: getstatic #2; //Field $assertionsDisabled:Z
7: ifne 22
10: aload_1
11: ifnonnull 22
14: new #3; //class java/lang/AssertionError
17: dup
18: invokespecial #4; //Method java/lang/AssertionError."<init>":()V
21: athrow
22: return
static {};
Code:
0: ldc_w #5; //class Foo
3: invokevirtual #6; //Method java/lang/Class.desiredAssertionStatus:()Z
6: ifne 13
9: iconst_1
10: goto 14
13: iconst_0
14: putstatic #2; //Field $assertionsDisabled:Z
17: return
Note line 7, which is a conditional branch dependent upon whether or not assertions are enabled. Thus if you have a class with a plain Java assert
in it, you'll have this branch somewhere in the bytecode, and this is what produces the "N/2 branches executed" coverage warning on the class declaration, where N is either 0 or 1 depending upon if the class was ever exercised by a test (1) or not (0).
Edit: note that this is also mentioned in https://sourceforge.net/apps/trac/eclemma/wiki/FilteringOptions:
Blocks that throw AssertionErrors - Entire block should be ignored if a condition (if !assertion throw new AssertionError)