switch
からアドレッシングモードを抽出するString
ステートメントがあり、カバーするユニットテストを作成しました。私はすべての不測の事態であると考えていましたが、JaCoCoはswitch
ステートメントをスキップし、カバレッジが低くなります。
デフォルトを含むすべてのcase
ステートメントがテストで実行されている場合、switch
ステートメントはヒットとしてカウントされないのはなぜですか?
( CodeCov に表示されるテスト結果を参照)
文字列による切り替えの場合
class Fun {
static int fun(String s) {
switch (s) {
case "I":
return 1;
case "A":
return 2;
case "Z":
return 3;
case "ABS":
return 4;
case "IND":
return 5;
default:
return 6;
}
}
}
Oracle Javaコンパイラーは、次のコードに類似したバイトコードを生成します(Javaは、わずかに異なるバイトコードを生成します)
int c = -1;
switch (s.hashCode()) {
case 65: // +1 branch
if (s.equals("I")) // +2 branches
c = 0;
break;
case 73: // +1 branch
if (s.equals("A")) // +2 branches
c = 1;
break;
case 90: // +1 branch
if (s.equals("Z")) // +2 branches
c = 2;
break;
case 64594: // +1 branch
if (s.equals("ABS")) // +2 branches
c = 3;
break;
case 72639: // +1 branch
if (s.equals("IND")) // +2 branches
c = 4;
break;
default: // +1 branch
}
switch (c) {
case 0: // +1 branch
return 1;
case 1: // +1 branch
return 2;
case 2: // +1 branch
return 3;
case 3: // +1 branch
return 4;
case 4: // +1 branch
return 5;
default: // +1 branch
return 6;
}
したがって、6ケースの元のスイッチ文は、hashCode
of String
に6ケースのスイッチと、5つのif文と6ケースの別のスイッチのバイトコードで表されます。このバイトコードを表示するには、javap -c
を使用できます。
JaCoCoはバイトコードの分析を実行し、0.8.0より前のバージョンでは、文字列による切り替え用のフィルターはありません。テストでは、if文の条件がtrue
に評価されるケースをカバーしていますが、false
に評価されるケースはカバーしていません。目標は、コンパイラが適切なコードを生成することをテストすることではなく、アプリケーションが正しく動作することをテストすることです。しかし、この答えを完全にするために、すべてのバイトコードブランチをカバーするテストを次に示します。
import org.junit.Test;
import static org.junit.Assert.*;
public class FunTest {
@Test
public void test() {
// original strings:
assertEquals(1, Fun.fun("I"));
assertEquals(2, Fun.fun("A"));
assertEquals(3, Fun.fun("Z"));
assertEquals(4, Fun.fun("ABS"));
assertEquals(5, Fun.fun("IND"));
// same hash codes, but different strings:
assertEquals(6, Fun.fun("\0I"));
assertEquals(6, Fun.fun("\0A"));
assertEquals(6, Fun.fun("\0Z"));
assertEquals(6, Fun.fun("\0ABS"));
assertEquals(6, Fun.fun("\0IND"));
// distinct hash code to cover default cases of switches
assertEquals(6, Fun.fun(""));
}
}
そして、証拠としてJaCoCo 0.7.9によって生成されたレポート:
JaCoCoバージョン0.8.0はフィルターを提供します 、javac
が文字列によるスイッチ用に生成するバイトコードのフィルターを含みます。したがって、追加のテストがなくても次のレポートが生成されます。