我对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/它说的是
在包含某些布尔表达式的每一行代码中,条件覆盖率仅回答以下问题:'每个布尔表达式都被评估为true和false吗?'。这是在单元测试执行期间遵循的流量控制结构中可能条件的密度]
任何人都知道这实际上是如何工作的,以及我在这里做错了什么?
来自类似问题(例如“ Why is JaCoCo not covering my String switch statements?”和“ How does assert groupType != null contain 4 branches”))>
JaCoCo执行字节码分析
因此类似-看一下字节码。
对于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个分支(每个条件跳转指令
ifeq
和ifne
每个分支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
仅包含四个分支。