gradle - SonarQube,JaCoCo :(应该是22个条件中的11个)应该是3个(或4个)

标签 gradle groovy sonarqube jacoco

我对SonarQube如何计算测试涵盖的条件一无所知。

使用的工具版本:
* JaCoCo 0.8.1
* SonarQube 7.4

这是我的常规代码

    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文档
https://docs.sonarqube.org/latest/user-guide/metric-definitions/
它在哪里说

On each line of code containing some boolean expressions, the condition coverage simply answers the following question: 'Has each boolean expression been evaluated both to true and false?'. This is the density of possible conditions in flow control structures that have been followed during unit tests execution



有人对这实际上如何工作以及我在这里做错了什么有想法吗?

最佳答案

来自类似的问题(例如“Why is JaCoCo not covering my String switch statements?”和“How does assert groupType != null contain 4 branches”)

JaCoCo performs analysis of bytecode



因此,类似地-看一下字节码。

对于Example.groovy
class Example {
    boolean condition2(boolean b1, boolean b2) {
        b1 || b2
    }
}

Groovy编译器(groovyc --version)
Groovy compiler version 3.0.0-rc-1
Copyright 2003-2019 The Apache Software Foundation. http://groovy-lang.org/

生成(groovyc Example.groovy)
以下字节码(javap -v -p Example.class)
  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

其中包含14个分支(每个条件跳转指令ifeqifne每个分支2个分支),并且您的测试仅覆盖其中的一半(执行路径,偏移ifeq处的第一个7跳转到偏移25),这与JaCoCo报告的内容完全一致因此显示在SonarQube中。

而且下面的讨论似乎在这里很重要-http://groovy.329449.n5.nabble.com/Branch-coverage-issues-td5686725.html,因为使用--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个分支。

关于gradle - SonarQube,JaCoCo :(应该是22个条件中的11个)应该是3个(或4个),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58453140/

相关文章:

java.lang.IllegalStateException : Not a JSON Object 错误

android - Android Studio 中的库 - 如何不生成完整副本

gradle - 在多模块 Gradle 构建中从根访问子模块依赖项

android - 失败:生成失败,发生异常。在volley\bintray.gradle中

gradle - 从构建脚本获取所有 Gradle 任务的列表

groovy - 将元素追加到列表中会在 Groovy 中创建列表的列表

gradle - 如何将 JHipster 生成的项目拆分为多模块 gradle 项目

Groovy:为什么同一个包中的类需要导入?

python - 从 setup.py 运行 Sonar 扫描仪

ubuntu - 将 SonarQube 的端口更改为 80