これは、Sonar の JaCoCo コード カバレッジ コンポーネントに関連する問題のようです。JaCoCo は、Java ソースではなく、コンパイルされたバイトコードで動作し、Java コンパイラは、基になるソースに直接関係しないコードを生成できます。
JaCoCoのドキュメントを見ると、次のようなセクションがあります (強調を追加)。
場合によっては、特定の行が強調表示されたり、特定の色になったりする理由が明らかでないことがあります。その理由は、基礎となるコード カバレッジ ライブラリ JaCoCo が Java クラス ファイルでのみ機能するためです。場合によっては、Java コンパイラがソース コードの特定の行に対して余分なバイト コードを作成します。このような状況は、JaCoCo/EclEmma の将来のバージョンでフィルタリングされる可能性があります。
パッセージのリンクをたどると、Jacoco の GH サイトのFilteringOptionsページに移動し、JDK がこれらの「偽の」コード カバレッジ警告をトリガーするコードを生成する可能性のある多くの方法について言及しています。
ただし、それはここで行われていることではありません (正確にはそうではありません)。
前述のように、JaCoCo は Java バイトコードで動作するため、ソースに直接起因しないコンパイラによって生成されたコードはすべてカバレッジにカウントされます。
私の特定のケースでassert
は、ソースには、アサートが発生した時点でのブランチを表すだけでなく、「グローバル」レベルでもブランチがありました。Foo
上で定義したクラスのバイトコードを見ると( を実行javap -c Foo
)、次のように表示されます。
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
行 7 に注意してください。これは、アサーションが有効かどうかに依存する条件分岐です。したがって、プレーンな Java を含むクラスがある場合assert
、バイトコードのどこかにこのブランチがあり、これがクラス宣言で「N/2 ブランチが実行されました」というカバレッジ警告を生成するものです。ここで、N は 0 またはクラスがテストによって実行されたことがあるか (1) ないか (0) に応じて 1。
編集:これはhttps://sourceforge.net/apps/trac/eclemma/wiki/FilteringOptionsにも記載されていることに注意してください:
AssertionErrors をスローするブロック - 条件の場合 (!assertion が新しい AssertionError をスローする場合)、ブロック全体を無視する必要があります。