jacoco 分支覆盖和声纳条件覆盖有什么区别?

Alb*_*ban 6 java code-coverage jacoco sonarqube sonarqube-scan

我正在尝试使用 SonarQube Scanner(版本 3.1.0.1141)分析 java 代码。

  • SonarQube 版本:5.6.6
  • 声纳 Java 插件版本:4.12.0.11033
  • 雅可可版本:0.8.0

我已经用这些属性填充了 sonar-project.properties :

# Sonar sources and metadata
sonar.language=java
sonar.sources=src/main
sonar.java.source=1.8
sonar.sourceEncoding=UTF-8
sonar.java.binaries=target/classes
sonar.java.libraries=target/lib

sonar.tests=src/test
sonar.java.coveragePlugin=jacoco
sonar.junit.reportsPath=target/surefire-reports
sonar.surefire.reportsPath=target/surefire-reports
Run Code Online (Sandbox Code Playgroud)

虽然 jacoco 报告给了我一个班级的结果:

  • 覆盖率:84%
  • 分行覆盖率:71%
  • 错过:9
  • 复杂度:24
  • 错过:6
  • 行数:69
  • 错过:0
  • 方法 : 8
  • 错过:0
  • 班级:1

SonarQube 显示测量值:

  • 条件覆盖率62.5%
  • 覆盖率81.7%
  • 线路覆盖率92.8%
  • 行覆盖69
  • 整体状况覆盖率62.5%
  • 总覆盖率81.7%
  • 总线路覆盖率92.8%
  • 整体未覆盖分支15
  • 整体裸露线5
  • 未覆盖的树枝15
  • 未覆盖的线5

根据声纳指标定义页面,条件覆盖的声纳键是 branch_coverage,所以我认为条件和分支覆盖是同一件事。

如何解释不同的结果?

Ger*_*cke 7

鉴于你有一些构造

if(a == 1 && b == 2) {
  //do this
} else {
  //do that
}
Run Code Online (Sandbox Code Playgroud)

你有两个分支

  • 做这个
  • 去做

和两个条件

  • a == 1 (cond1)
  • b == 2 (cond2)

如果你有两个测试用例

  • 测试(a == 1,b == 2)
  • 测试(a == 2,b == 2)

您覆盖了两个分支,因为 (cond1 && cond2) 的组合条件要么为假,要么为真,

但是你只覆盖了 cond1 并且只覆盖了 cond2 的一半,即 75% 的条件覆盖率。

要获得完整的条件覆盖,您需要进行额外的测试

  • 测试(a == 1,b == 1)

编辑

这两种工具都使用每行的分支信息来计算覆盖率。我对我的一些代码进行了测试,“要覆盖的条件”(Sonarqube)的数量与 Jacoco 报告中的“分支”总数相匹配 - 但我使用了最新版本的 jacoco 和 Sonarqube/sonar-java。因此,除了名称之外,措施是/应该是相同的。

但是鉴于您提供的数字,您的分析总体上似乎有些奇怪。不同的不仅是百分比值,还有绝对值(Jacoco 中有 9 个未覆盖的分支,而 Sonarqube 中有 15 个未覆盖的分支)。

所以我检查了你使用的版本 - jacoco 0.8.0 和使用 jacoco 0.7.9 的 sonar-java 插件 v4.11.0.11033。

Jacoco 0.8.0发行说明阅读

在创建报告期间,各种编译器生成的工件被过滤掉,否则需要不必要的甚至有时不可能的技巧来避免部分或遗漏的覆盖:

  • 方法 valueOf 和枚举类型的值 (GitHub #491)。
  • 私有空无参数构造函数(GitHub #529)。
  • 用@lombok.Generated 注释的方法可以更好地与 Lombok >= 1.16.14 集成。Rüdiger zu Dohna (@t1) (GitHub #513) 的初步分析和贡献。
  • 用 @groovy.transform.Generated 注释的方法可以更好地与 Groovy >= 2.5.0 集成。感谢 Andres Almiray (@aalmiray) 将注释添加到 Groovy (GitHub #610)。
  • 同步块字节码的一部分(GitHub #501)。
  • try-with-resources 语句的字节码的一部分(GitHub #500)。
  • finally 块的部分字节码(GitHub #604)。
  • java.lang.String 值上 switch 语句的字节码的一部分(GitHub > #596)。

所以我最好的猜测是,Jacoco 0.8.0 生成的报告过滤掉了一些提到的生成的工件,有效地减少了分支总数。然而,Sonar-Java 使用 Jacoco 0.7.9,它不会过滤掉生成的工件,因此数字更高(覆盖率更低)。

也许您应该将 jacoco 版本降级到 0.7.9 或升级 sonar-java 插件。