开关的eclemma分支覆盖:错过了7个 [英] eclemma branch coverage for switch: 7 of 19 missed

查看:343
本文介绍了开关的eclemma分支覆盖:错过了7个的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个交换机系统,我正在使用eclemma来测试分支机构的覆盖范围。我们需要至少有80%的分支机构覆盖所有内容,所以我尽可能地尝试测试。
然而,eclemma告诉我这个交换系统在分支覆盖范围方面没有经过全面测试。

I have this switch system and I'm using eclemma to test the branch coverage. We are required to have at least 80% in branch coverage for everything so I'm trying to test as much as possible. However, eclemma tells me this switch system is not fully tested in terms of branch coverage.

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个个案+所有未定义)。

I used straightforward JUnit tests to go trough each of these cases. Still eclemma marks this as yellow and says "7 of 19 branches missed". I would say there are only 7 ways to go through this switch system (the 6 individual cases+all undefined).

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

I tried searching for similar questions on stack overflow. Some of them had as solutions to use if/else for full coverage. I'm not sure if this is the only way possible to get this coverage.

任何人都可以解释所有这19个分支来自何处以及如何测试这些分支7在这个交换机案例中得到100%的分支覆盖率?

Can anybody explain where all these 19 branches come from and how I could test these remaining 7 to get a 100% branch coverage on this switch case?

推荐答案

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

The Java compiler translates the switch-case code either to a tableswitch or to a lookupswitch. The tableswitch is used when there are only a few gaps are between the different cases. Otherwise, the lookupswitch is used.

在您的情况下, tableswitch <使用/ code> ,因为你的案例的哈希码是紧密间隔的(与owaism引用的代码不同):

In your case a tableswitch is used because the hash codes of your cases are closely spaced (unlike in the code referenced by 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值。)

The numbers to the left of the colon are the ordered hash codes and the filled gaps between them, the numbers to the right are the jump destinations. (In Java, the hash code of a character is its ASCII value.)

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

68 is the hash code of "D" (the lowest one), and 83 is the hash code of "S" (the highest one). 69 is the value of one of the gaps between the real cases and will jump to the default case.

但是,我假设EclEmma从 tableswitch 的覆盖率计算中排除了这些分支(由于这些差距,它会进一步降低覆盖率)。
所以我们还有 0(计数)分支。

However, I assume that EclEmma excludes these branches from the coverage computation of a tableswitch (it would lower the coverage even more because of the gaps). So we have 0 (counted) branches yet.

接下来,在每次跳转时执行等于字符串值的比较目的地(默认情况除外)。由于您的开关案例由6个案例组成,我们有6个6个跳转目标,并且等于比较。

Next, an equals comparison of the string value is performed at each jump destination (except at the one of the default case). As your switch-case consists of 6 cases, we have 6 six jump destinations with an equals comparison.

案例G的比较字节代码如下:

The byte code of the comparison for case "G" is below:

  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分支用于比较。(默认情况下不分支。)

EclEmma counts two branches: either the input string and the case string are equals or they are not. Thus, we have 6 * 2 branches for the comparisons. (The default case does not branch.)

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

Next, if the two strings are equal the index of the case will be stored (byte code lines 105-106 for the case "G"). Then a jump to the second tableswitch will be executed. Otherwise, the jump will be executed directly.

 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个案例加上默认情况)。

This switch operates on the previously stored case index and jumps to the code in the case (case "G" has index 0, the default case has -1). EclEmma counts 7 branches (6 cases plus the default case).

因此,我们在第一个 tableswitch 中的12个分支等于比较以及第二个 tableswitch中的另外7个分支 。总而言之,会产生19个分支。

Consequently, we have 0 counted branches in the first tableswitch, 12 branches in the equals comparisons and further 7 branches in the second tableswitch. All in all, this results in 19 branches.

您的测试不会覆盖6个不等于分支中的任何一个。
为了覆盖这些分支,您需要为每种情况找到一个不等于大小写条件但具有相同哈希码的字符串。
有可能,但最终不合理......

Your tests do not cover any of the 6 not-equals branches. In order to cover these, you would need to find a string for each case which is not equal to the case condition but has the same hash code. It is possible, but definitively not sensible...

可能未来将调整EclEmma的分支计数。

Probably, the branch counting of EclEmma will be adjusted in the future.

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

Moreover, I guess you don't have a test case which does not match with any of the cases (thus the (implicit) default case is not covered.)

这篇关于开关的eclemma分支覆盖:错过了7个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆