开关的eclemma分支覆盖范围:19个错过了7个

Gaa*_*god 26 java testing code-coverage switch-statement eclemma

我有这个交换机系统,我正在使用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;
        }
Run Code Online (Sandbox Code Playgroud)

我使用简单的JUnit测试来解决这些问题.仍然是eclemma将此标记为黄色并且说"错过了19个分支中的7个".我想说只有7种方法可以通过这个开关系统(6个个案+所有未定义).

我尝试在堆栈溢出时搜索类似的问题.他们中的一些人使用if/else进行完全覆盖的解决方案.我不确定这是否是获得此保险的唯一方法.

任何人都可以解释所有这19个分支来自何处以及我如何测试这些剩余的7个以获得100%的分支覆盖率?

nra*_*ner 32

Java编译器将switch-case代码转换为a tableswitch或a lookupswitch.在tableswitch当只有少数差距是,不同的情况之间使用.否则,lookupswitch使用.

在你的情况下使用a 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
      }
Run Code Online (Sandbox Code Playgroud)

冒号左边的数字是有序哈希码和它们之间填充的间隙,右边的数字是跳转目的地.(在Java中,字符的哈希码是其ASCII值.)

68是"D"(最低的)83的哈希码,并且是"S"(最高的)的哈希码. 69是真实案例之间的差距之一的值,并将跳转到默认情况.

但是,我假设EclEmma从a的覆盖计算中排除了这些分支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_3
Run Code Online (Sandbox Code Playgroud)

EclEmma计算两个分支:输入字符串和大小写字符串是等于或不是.因此,我们有6*2个分支用于比较.(默认情况下不分支.)

接下来,如果两个字符串相等,则将存储情况的索引(105-106情况"G"的字节代码行).然后跳转到第二个tableswitch将被执行.否则,跳转将直接执行.

 185: tableswitch   { // 0 to 5
                 0: 224
                 1: 237
                 2: 250
                 3: 263
                 4: 276
                 5: 289
           default: 299
      }
Run Code Online (Sandbox Code Playgroud)

此开关对先前存储的案例索引进行操作并跳转到案例中的代码(案例"G"具有索引0,默认情况下具有索引-1).EclEmma有7个分支(6个案例加上默认案例).

因此,我们tableswitchequals比较中的第一个12个分支中有0个计数分支,在第二个中有7个分支tableswitch.总而言之,这导致19个分支.


您的测试不包括6个不等于分支中的任何一个. 为了覆盖这些,您需要为每种情况找到一个字符串,该字符串不等于大小写条件但具有相同的哈希码.这是可能的,但绝对不明智......

可能,EclEmma的分支计数将在未来进行调整.

此外,我猜你没有一个与任何情况都不匹配的测试用例(因此不包括(隐式)默认情况.)