首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >交换机的eclemma分支覆盖: 19个分支中有7个未命中

交换机的eclemma分支覆盖: 19个分支中有7个未命中
EN

Stack Overflow用户
提问于 2015-01-19 03:14:25
回答 2查看 13.7K关注 0票数 28

我有这个交换机系统,并且我正在使用eclemma来测试分支覆盖率。我们被要求至少有80%的分支机构覆盖率,所以我试图尽可能多地进行测试。然而,eclemma告诉我,这个交换机系统并没有在分支覆盖方面进行充分的测试。

代码语言:javascript
复制
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%的分支覆盖率?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-01-19 05:50:47

Java编译器将switch-case代码转换为tableswitchlookupswitch。当不同的情况之间只有几个间隙时,就会使用tableswitch。否则,将使用lookupswitch

在您的例子中,散列tableswitch使用,因为您的案例的散列代码是紧密间隔的(与owaism引用的代码不同):

代码语言:javascript
复制
  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“的比较字节码如下:

代码语言:javascript
复制
  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

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

接下来,如果两个字符串相等,则将存储案例的索引(案例“G”的字节码行105-106 )。然后将执行到第二个tableswitch的跳转。否则,将直接执行跳转。

代码语言:javascript
复制
 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的分支计数将在未来进行调整。

此外,我猜您没有与任何用例不匹配的测试用例(因此不包括(隐式)默认用例。)

票数 36
EN

Stack Overflow用户

发布于 2015-01-19 04:04:38

查看以下链接:http://sourceforge.net/p/eclemma/discussion/614869/thread/80e770df/

下面是来自上面链接的代码片段:

这是一个有3种情况的开关的例子:

,这是一个相当有趣的观察结果。从字节码可以看出Java编译器是如何处理字符串上的开关的。实际上,这是一个3步的过程:

  1. 开关上的散列代码(3个分支,1个默认值)
  2. 为每个散列代码做一个等于(3 *2个分支)
  3. 为实际执行的情况做一个最后的切换(3个分支,1个默认值)

因此,我们总共有14个分支,从源代码的角度来看,这看起来很奇怪。看起来更奇怪的是你少了其中的三个。解释是在步骤2中,在散列代码之后另外应用equals方法。为了涵盖这些分支,您还需要查找具有相同散列代码的其他字符串。这绝对是未来版本的JaCoCo中可能会从覆盖率报告中过滤掉的东西:

https://sourceforge.net/apps/trac/eclemma/wiki/FilteringOptions

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28013717

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档