JaCoCo为什么不涵盖我的String开关语句? [英] Why is JaCoCo not covering my String switch statements?

查看:73
本文介绍了JaCoCo为什么不涵盖我的String开关语句?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个switch语句,该语句从String中提取了寻址模式,并且我编写了单元测试来进行介绍,我认为这是所有可能的情况,但JaCoCo似乎跳过了我的switch语句,从而降低了覆盖范围.

I have a switch statement that extracts an addressing mode from a String and I've written unit tests to cover, what I thought was every eventuality but JaCoCo seems to skip my switch statements, resulting in lower coverage.

为什么,如果我的所有case语句(包括默认值)都在测试中执行,那么switch语句是否不算作命中?

Why, if all my case statements, including a default are being executed in tests, would the switch statement not be counted as hit?

(请参阅

推荐答案

通过字符串进行切换

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的Eclipse Compiler生成的字节码略有不同)

Oracle Java compiler generates bytecode similar to the following code (Eclipse Compiler for Java generates slightly different bytecode)

    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 String的6种情况的开关加上5种if语句加上具有6种情况的另一个开关在字节码中表示.要查看此字节码,可以使用javap -c.

So that original switch-statement with 6 cases is represented in bytecode by a switch with 6 cases for hashCode of String plus 5 if-statements plus another switch with 6 cases. To see this bytecode you can use javap -c.

JaCoCo执行字节码分析,并且在低于0.8.0的版本中没有用于按字符串切换的过滤器.您的测试涵盖了if语句中的条件评估为true的情况,而不涉及其评估为false的情况.我个人建议不要忽略丢失的情况,因为目标不是测试编译器生成正确的代码,而是测试应用程序的行为.但是为了这个答案的完整起见-这是涵盖所有字节码分支的测试:

JaCoCo performs analysis of bytecode and in versions lower than 0.8.0 has no filter for switch by string. Your tests cover cases, where conditions in if-statements evaluate to true, but not the cases where they evaluate to false. Personally I would advise to simply ignore missing cases, because the goal is not to test that compiler generates proper code, but to test that your application behaves correctly. But for a sake of completeness of this answer - here is tests that cover all bytecode branches:

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生成的报告作为证明:

And report generated by JaCoCo 0.7.9 as a proof:

JaCoCo 0.8.0版提供了过滤器,包括javac为按字符串切换而生成的字节码过滤器.因此,即使没有其他测试,也会生成以下报告:

JaCoCo version 0.8.0 provides filters, including filter for bytecode that javac produces for switch by string. And so generates following report even without additional tests:

这篇关于JaCoCo为什么不涵盖我的String开关语句?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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