Gradle SonarQube,JaCoCo:(22种情况中的11种)当它们应该是3(或4)时

Gradle SonarQube,JaCoCo:(22种情况中的11种)当它们应该是3(或4)时,gradle,groovy,sonarqube,jacoco,Gradle,Groovy,Sonarqube,Jacoco,我不知道SonarQube是如何计算测试覆盖的条件的 所用工具的版本: *JaCoCo 0.8.1 *声纳qube 7.4 这是我的groovy代码 boolean condition1(boolean b1, boolean b2) { !b1 || !b2 } boolean condition2(boolean b1, boolean b2) { b1 || b2 } boolean condition3(bool

我不知道SonarQube是如何计算测试覆盖的条件的

所用工具的版本: *JaCoCo 0.8.1 *声纳qube 7.4

这是我的groovy代码

    boolean condition1(boolean b1, boolean b2) {
        !b1 || !b2
    }

    boolean condition2(boolean b1, boolean b2) {
        b1 || b2
    }

    boolean condition3(boolean b1, boolean b2) {
        !b1 && !b2
    }

    boolean condition4(boolean b1, boolean b2) {
        b1 && b2
    }

    boolean condition5(boolean b1, boolean b2) {
        b1 && !b2
    }

    boolean condition6(boolean b1, boolean b2, boolean b3) {
        b1 && b2 && b3
    }
以下是测试

    void "test condition 1"() {
        expect:
        service.condition1(c1,c2)

        where:
        c1    | c2
        true  | true
        true  | false
        false | true
        false | false
    }

    void "test condition 2"() {
        expect:
        service.condition2(c1,c2)

        where:
        c1    | c2
        true  | true
        true  | false
        false | true
        false | false
    }

    void "test condition 3"() {
        expect:
        service.condition3(c1,c2)

        where:
        c1    | c2
        true  | true
        true  | false
        false | true
        false | false
    }

    void "test condition 4"() {
        expect:
        service.condition4(c1,c2)

        where:
        c1    | c2
        true  | true
        true  | false
        false | true
        false | false
    }

    void "test condition 5"() {
        expect:
        service.condition5(c1,c2)

        where:
        c1    | c2
        true  | true
        true  | false
        false | true
        false | false
    }

    void "test condition 6"() {
        expect:
        service.condition6(c1, c2, c3)

        where:
        c1    | c2    | c3
        true  | true  | true
        true  | true  | false
        true  | false | true
        true  | false | false
        false | true  | true
        false | true  | false
        false | true  | true
        false | true  | false
        false | false | false
    }
代码覆盖率报告说这些条件不满足,以下是我得到的唯一信息

condition1. (11 of 22 conditions)
condition2. (7 of 14 conditions)
condition3. (11 of 22 conditions)
condition4. (7 of 14 conditions)
condition5. (9 of 18 conditions)
condition6. (11 of 22 conditions)
这意味着我无法达到100%的覆盖测试,尽管我相信逻辑上做到了

我了解SonarQube文档 上面写着

在包含一些布尔表达式的每一行代码中,条件覆盖率都简单地回答了以下问题:“每个布尔表达式的计算结果是否同时为true和false?”。这是单元测试执行期间遵循的流控制结构中可能条件的密度


有人知道这到底是怎么回事,我做错了什么吗?

来自类似的问题,如和

JaCoCo执行字节码分析

因此,类似地,看看字节码

例如,groovy

Groovy编译器groovyc-版本

生成groovyc Example.groovy 下面是字节码javap-v-p Example.class

它包含14个分支,每个条件跳转指令ifeq和ifne包含2个分支,并且您的测试只覆盖其中的一半执行路径,其中偏移量7处的第一个ifeq跳转到偏移量25,这与JaCoCo报告的结果完全一致,因此在SonarQube中显示

下面的讨论似乎与此相关,因为使用-indy选项groovyc-indy Example.groovy编译相同的代码会产生以下字节码

  public boolean condition2(boolean, boolean);
    descriptor: (ZZ)Z
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=3, args_size=3
         0: iload_1
         1: ifne          8
         4: iload_2
         5: ifeq          12
         8: iconst_1
         9: goto          13
        12: iconst_0
        13: ireturn
        14: nop
        15: nop
        16: nop
        17: nop
        18: nop
        19: nop
        20: nop
        21: nop
        22: athrow
      LineNumberTable:
        line 3: 0
        line 4: 14
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      14     0  this   LExample;
            0      14     1    b1   Z
            0      14     2    b2   Z

只包含4个分支。

来自类似问题,如和

JaCoCo执行字节码分析

因此,类似地,看看字节码

例如,groovy

Groovy编译器groovyc-版本

生成groovyc Example.groovy 下面是字节码javap-v-p Example.class

它包含14个分支,每个条件跳转指令ifeq和ifne包含2个分支,并且您的测试只覆盖其中的一半执行路径,其中偏移量7处的第一个ifeq跳转到偏移量25,这与JaCoCo报告的结果完全一致,因此在SonarQube中显示

下面的讨论似乎与此相关,因为使用-indy选项groovyc-indy Example.groovy编译相同的代码会产生以下字节码

  public boolean condition2(boolean, boolean);
    descriptor: (ZZ)Z
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=3, args_size=3
         0: iload_1
         1: ifne          8
         4: iload_2
         5: ifeq          12
         8: iconst_1
         9: goto          13
        12: iconst_0
        13: ireturn
        14: nop
        15: nop
        16: nop
        17: nop
        18: nop
        19: nop
        20: nop
        21: nop
        22: athrow
      LineNumberTable:
        line 3: 0
        line 4: 14
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      14     0  this   LExample;
            0      14     1    b1   Z
            0      14     2    b2   Z

只包含4个分支。

欢迎使用StackOverflow!请阅读并提供完整的可复制示例,即您的Groovy代码。感谢您的指导。刚刚改变了问题:欢迎来到StackOverflow!请阅读并提供完整的可复制示例,即您的Groovy代码。感谢您的指导。只是换了个问题:非常感谢你的回答。这解释了很多我正在努力使我的GRAIL应用程序使用CuffKyDype选项,这样我就可以确定这会修复我的问题,但一般来说我对这里的上下文有一个更清晰的看法。@ DavideBarbuto,请考虑接受投票和标记答案作为接受-非常感谢你的答案。这解释了很多我正在努力使我的GRAIL应用程序使用CuffKyDype选项,这样我就可以确定这会修复我的问题,但一般来说,我对这里的上下文有一个更清楚的认识。@ DavideBarbuto,请考虑接受投票和标记答案作为接受。
  public boolean condition2(boolean, boolean);
    descriptor: (ZZ)Z
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=4, args_size=3
         0: invokestatic  #20                 // Method $getCallSiteArray:()[Lorg/codehaus/groovy/runtime/callsite/CallSite;
         3: astore_3
         4: invokestatic  #38                 // Method org/codehaus/groovy/runtime/BytecodeInterface8.isOrigZ:()Z
         7: ifeq          25
        10: getstatic     #40                 // Field __$stMC:Z
        13: ifne          25
        16: invokestatic  #43                 // Method org/codehaus/groovy/runtime/BytecodeInterface8.disabledStandardMetaClass:()Z
        19: ifne          25
        22: goto          42
        25: iload_1
        26: ifne          33
        29: iload_2
        30: ifeq          37
        33: iconst_1
        34: goto          38
        37: iconst_0
        38: ireturn
        39: nop
        40: nop
        41: athrow
        42: iload_1
        43: ifne          50
        46: iload_2
        47: ifeq          54
        50: iconst_1
        51: goto          55
        54: iconst_0
        55: ireturn
        56: nop
        57: nop
        58: nop
        59: nop
        60: nop
        61: nop
        62: nop
        63: nop
        64: athrow
      LineNumberTable:
        line 2: 4
        line 3: 25
        line 4: 39
        line 3: 42
        line 4: 56
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      56     0  this   LExample;
            0      56     1    b1   Z
            0      56     2    b2   Z
  public boolean condition2(boolean, boolean);
    descriptor: (ZZ)Z
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=3, args_size=3
         0: iload_1
         1: ifne          8
         4: iload_2
         5: ifeq          12
         8: iconst_1
         9: goto          13
        12: iconst_0
        13: ireturn
        14: nop
        15: nop
        16: nop
        17: nop
        18: nop
        19: nop
        20: nop
        21: nop
        22: athrow
      LineNumberTable:
        line 3: 0
        line 4: 14
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      14     0  this   LExample;
            0      14     1    b1   Z
            0      14     2    b2   Z