17

Java/Junit では、何らかのオブジェクトで null をテストする必要があります。条件をテストするにはさまざまな方法がありますが、ほとんどのテストで assertTrue を使用しています。assertTrue で null をチェックすると、EclEmma は 1 つのブランチのみをテストしていると述べています。

手動でステートメントを変数に解決すると (結果をブール値に設定して assertTrue に渡すなど)、コード カバレッジは assert で完了したと見なされますが、変数の初期化行では完了したと見なされません。

なぜこうなった?これは、 http://sourceforge.net/apps/trac/eclemma/wiki/FilteringOptionsで言及されているように、Java が明らかに追加する余分なバイト コードに関連していますか? 任意の解決策 (他の assert ステートメントの使用を除く)。

true をアサート:

assertTrue( myObject == null ); //1 of 2 branches

true をアサート:

boolean test = (myObject == null); //1 of 2 branches missing
assertTrue(test); // complete

assertNull:

assertNull( myObject ) //complete;
4

3 に答える 3

21

ほとんどのブール式では、Java コンパイラはバイト コードに追加の分岐を生成します。JaCoCo は、元の Java コードではなく、生成されたバイト コードに基づいて「ブランチ カバレッジ」を生成するため、使用するほぼすべてのブール式の追加のブランチ カバレッジ情報が表示されます。

コードで使用するブール式は ですmyObject == null

この値を計算するために、Java コンパイラは 2 つの引数をスタックにプッシュするコードを生成し、スタックに 1 (真) または 0 (偽) をプッシュするために条件付きジャンプを実行します。JaCoCo は、この条件付きジャンプの分岐カバレッジをレポートします。

したがって、使用するという事実は、myObject == null説明した動作をトリガーします。

他の例として、これを試してください:

boolean t = true;
boolean f = false;
boolean result1 = (t && f) || f; // 3 out of 6 missed.
boolean result2 = !t;            // 1 out of 2 missed.

これは、たとえば、ブール式が関数によって返され、if-then-else ステートメントの条件として別の場所で使用される場合に役立ちます。ほとんどの場合、Java コンパイラーの動作の結果ですが、元の Java コードの(単なる分岐カバレッジではなく)条件カバレッジを評価するのに役立ちます。

この機能は十分に文書化されていませんが、以下にいくつかの指針を示します。

したがって、実際には、余分なバイトコードが生成されることに関連していますが、フィルタリングオプションが意図されている合成バイトコンパイラ構造の特定の例には関連していません。

注:最初の回答は推測が多すぎたため、主要な編集を行いました。良い議論と批判的な議論をしてくれた @ira-baxter に感謝します。

于 2012-04-13T20:29:15.337 に答える
0

Emma が IMHO をカウントする (ブランチ) カバレッジの条件式を「ブランチのあるもの」として扱うという事実は、単純に壊れているようです。条件分岐ではありません。

Assert についてもっと議論することができます。「アサートの失敗時に例外をスローする」と定義されている場合、実際には条件分岐があります。[私が思うように、私はJavaの専門家ではありません]「アサートの失敗時にプログラムを終了する」と定義されている場合、それは実際にはブランチではありません。メソッド呼び出しも不明瞭です。これら、呼び出されたメソッドが例外をスローした場合、制御フローが「残りのステートメント」に進まないという意味での条件分岐です。

当社のJava テスト カバレッジツールは、そのような条件の (分岐) カバレッジ分析を「正しく」取得します。

于 2012-04-14T14:58:51.220 に答える