我有这个交换机系统,并且我正在使用eclemma来测试分支覆盖率。我们被要求至少有80%的分支机构覆盖率,所以我试图尽可能多地进行测试。然而,eclemma告诉我,这个交换机系统并没有在分支覆盖方面进行充分的测试。
pos = p.getCurrentPosition().substring(0, 1);
switch (pos) {
case "G":
goalkeepers++;
break;
case "D":
defense++;
break;
case "M":
midfield++;
break;
case "F":
offense++;
break;
case "S":
substitutes++;
break;
case "R":
reserves++;
break;
}我使用了简单的JUnit测试来检查每一个案例。尽管如此,eclemma仍将其标记为黄色,并显示“19个分支中有7个未命中”。我想说只有7种方法可以通过这个切换系统(6个单独的cases+all未定义)。
我尝试在堆栈溢出上搜索类似的问题。他们中的一些人使用if/else作为全面覆盖的解决方案。我不确定这是不是获得这个覆盖范围的唯一方法。
谁能解释一下这19个分支从何而来,以及我如何测试剩下的7个分支才能在此交换机案例中获得100%的分支覆盖率?
发布于 2015-01-19 05:50:47
Java编译器将switch-case代码转换为tableswitch或lookupswitch。当不同的情况之间只有几个间隙时,就会使用tableswitch。否则,将使用lookupswitch。
在您的例子中,散列tableswitch使用,因为您的案例的散列代码是紧密间隔的(与owaism引用的代码不同)::
16: tableswitch { // 68 to 83
68: 111 // 'D'
69: 183
70: 141 // 'F'
71: 96 // 'G'
72: 183
73: 183
74: 183
75: 183
76: 183
77: 126 // 'M'
78: 183
79: 183
80: 183
81: 183
82: 171 // 'R'
83: 156 // 'S'
default: 183
}冒号左边的数字是有序哈希码和它们之间填充的空格,右边的数字是跳转目的地。(在Java中,字符的哈希码是其ASCII值。)
68是"D“(最低的)的哈希码,83是"S”(最高的)的哈希码。69是实际情况之间的差距之一的值,并将跳到默认情况。
然而,我假设EclEmma从tableswitch的覆盖率计算中排除了这些分支(由于差距,它会进一步降低覆盖率)。所以我们已经有了0 (计数)分支。
接下来,在每个跳转目的地执行字符串值的相等比较(缺省情况除外)。由于您的切换案例由6个案例组成,因此我们有6个6个跳转目的地,并进行相等比较。
情况"G“的比较字节码如下:
96: aload_3
97: ldc #10
99: invokevirtual #11 java/lang/Object;)Z
102: ifeq 183
105: iconst_0
106: istore 4
108: goto 183
111: aload_3EclEmma计算两个分支:输入字符串和大小写字符串是否相等。因此,我们有用于比较的6 *2分支。(默认情况下不分支)。
接下来,如果两个字符串相等,则将存储案例的索引(案例“G”的字节码行105-106 )。然后将执行到第二个tableswitch的跳转。否则,将直接执行跳转。
185: tableswitch { // 0 to 5
0: 224
1: 237
2: 250
3: 263
4: 276
5: 289
default: 299
}此开关对先前存储的案例索引进行操作,并跳转到案例中的代码(案例"G“的索引为0,默认案例的索引为-1)。EclEmma计算7分支的数量(6个案例加上默认案例)。
因此,我们在第一个tableswitch中有0个计数的分支,在equals比较中有12个分支,在第二个tableswitch中还有7个分支。总而言之,这个有19个分支。
您的测试没有覆盖6个不等于分支中的任何一个。为了覆盖这些分支,您需要为每个案例找到一个字符串,该字符串不等于case条件,但具有相同的散列代码。这是可能的,但绝对是不明智的。
很可能,EclEmma的分支计数将在未来进行调整。
此外,我猜您没有与任何用例不匹配的测试用例(因此不包括(隐式)默认用例。)
发布于 2015-01-19 04:04:38
查看以下链接:http://sourceforge.net/p/eclemma/discussion/614869/thread/80e770df/
下面是来自上面链接的代码片段:
这是一个有3种情况的开关的例子:
,这是一个相当有趣的观察结果。从字节码可以看出Java编译器是如何处理字符串上的开关的。实际上,这是一个3步的过程:
因此,我们总共有14个分支,从源代码的角度来看,这看起来很奇怪。看起来更奇怪的是你少了其中的三个。解释是在步骤2中,在散列代码之后另外应用equals方法。为了涵盖这些分支,您还需要查找具有相同散列代码的其他字符串。这绝对是未来版本的JaCoCo中可能会从覆盖率报告中过滤掉的东西:
https://sourceforge.net/apps/trac/eclemma/wiki/FilteringOptions
https://stackoverflow.com/questions/28013717
复制相似问题