jacoco代码覆盖率报告生成器显示错误:“包中的类”代码覆盖率报告’与执行数据不匹配“

我使用jacoco:report标签生成jacoco报告。 我收到的错误如下:

[jacoco:report] Classes in bundle 'Code Coverage Report' do no match with execution data. For report generation the same class files must be used as at runtime. [jacoco:report] Execution data for class xxxxx does not match. [jacoco:report] Execution data for class yyyyy does not match. 

ant报告目标如下:

                   

这样生成的./code/src只能使用./code/src 。 那么为什么会出现这样的错误呢。 任何想法?

您收到与classID相关的错误。 这是JaCoCo docs-site详细描述的概念。 http://www.eclemma.org/jacoco/trunk/doc/classids.html 。 这是在同一JVM中支持多个版本的类(例如appserver)的关键步骤。

复制部分部分以获得可见性。

什么是类ID,它们是如何创建的?

类ID是64位整数值,例如hex表示法中的0x638e104737889183。 他们的计算被认为是JaCoCo的实施细节。 当前使用原始类文件的CRC64校验和创建ID。

什么可以导致不同的类ID?

类ID对于完全相同的类文件(逐字节)是相同的。 有几个原因可能会导致您获得不同的类文件。 如果您使用不同的工具链,首先编译Java源文件将导致不同的类文件:

  • 不同的编译器供应商(例如Eclipse与Oracle JDK)

  • 不同的编译版本

  • 不同的编译器设置(例如,调试与非调试)

此外,后处理类文件(混淆,AspectJ等)通常会更改类文件。 如果您只是为运行时和分析使用相同的类文件,JaCoCo将运行良好。 因此,创建这些类文件的工具链无关紧要。

即使文件系统上的类文件相同,JaCoCo运行时代理程序看到的类也可能不同。 这通常发生在JaCoCo代理或特殊类加载器预处理类文件之前配置另一个Java代理时。 典型的候选人是:

  • 模拟框架
  • 应用服务器
  • 持久性框架

同一页面涵盖了可能的解决方案

处理运行时修改的类有哪些变通方法?

如果在您的设置中在运行时修改了类,那么有一些解决方法可以使JaCoCo继续工作:

  • 如果使用其他Java代理,请确保首先在命令行中指定JaCoCo代理。 这样JaCoCo代理应该看到原始的类文件。
  • 指定JaCoCo代理的classdumpdir选项,并在生成报告时使用转储的类。 请注意,只会转储已加载的类,即根本未执行的类将不会显示在报表中,因为未涵盖。
  • 在运行测试之前使用脱机检测。 这样,在任何运行时修改发生之前,类都会由JaCoCo检测。 请注意,在这种情况下,报告必须使用原始类生成,而不是使用已检测的类生成。

编辑于2017年2月22日

如何使用离线仪器:使用Daniel Atallah提供的以下任务。

 //Additional SourceSets can be added to the jacocoOfflineSourceSets as needed by project.ext.jacocoOfflineSourceSets = [ 'main' ] task doJacocoOfflineInstrumentation(dependsOn: [ classes, project.configurations.jacocoAnt ]) { inputs.files classes.outputs.files File outputDir = new File(project.buildDir, 'instrumentedClasses') outputs.dir outputDir doFirst { project.delete(outputDir) ant.taskdef( resource: 'org/jacoco/ant/antlib.xml', classpath: project.configurations.jacocoAnt.asPath, uri: 'jacoco' ) def instrumented = false jacocoOfflineSourceSets.each { sourceSetName -> if (file(sourceSets[sourceSetName].output.classesDir).exists()) { def instrumentedClassedDir = "${outputDir}/${sourceSetName}" ant.'jacoco:instrument'(destdir: instrumentedClassedDir) { fileset(dir: sourceSets[sourceSetName].output.classesDir, includes: '**/*.class') } //Replace the classes dir in the test classpath with the instrumented one sourceSets.test.runtimeClasspath -= files(sourceSets[sourceSetName].output.classesDir) sourceSets.test.runtimeClasspath += files(instrumentedClassedDir) instrumented = true } } if (instrumented) { //Disable class verification based on https://github.com/jayway/powermock/issues/375 test.jvmArgs += '-noverify' } } } test.dependsOn doJacocoOfflineInstrumentation 

现在使用"gradlew test jacocoTestReport"命令生成报告。

JaCoCo需要与执行时使用的报告生成完全相同的类文件。 由于不同的编译器和/或修改类的其他工具,类可能不同。