[英]jacoco code coverage report generator showing error : "Classes in bundle 'Code Coverage Report' do no match with execution data"
我正在使用 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 报告目标如下所示:
<target name="report">
<jacoco:report>
<executiondata>
<file file="${jacocoexec.dir}/${jacocoexec.filename}"/>
</executiondata>
<!-- the class files and optional source files ... -->
<structure name="Code Coverage Report">
<classfiles>
<fileset file="./jar/abc.jar"/>
</classfiles>
<sourcefiles>
<fileset dir="./code/src"/>
</sourcefiles>
</structure>
<!-- to produce reports in different formats. -->
<html destdir="${jacoco.report.dir}"/>
</jacoco:report>
</target>
abc.jar
仅使用./code/src
生成。 那为什么会出现这样的错误。 任何想法?
您收到与 classID 相关的错误。 这是在 JaCoCo docs-site 上详细描述的概念。 http://www.eclemma.org/jacoco/trunk/doc/classids.html 。 这是在同一 JVM 中支持多个版本的类(例如应用程序服务器)的关键步骤。
在这里复制部分内容以供查看。
什么是类 ID,它们是如何创建的?
类 ID 是 64 位整数值,例如 0x638e104737889183 以十六进制表示法。 他们的计算被认为是 JaCoCo 的一个实现细节。 目前 id 是使用原始类文件的 CRC64 校验和创建的。
什么会导致不同的类 ID?
仅对于完全相同的类文件(逐字节),类 ID 是相同的。 您可能会获得不同的类文件有几个原因。 如果使用不同的工具链,首先编译 Java 源文件将产生不同的类文件:
不同的编译器供应商(例如 Eclipse 与 Oracle JDK)
不同的编译器版本
不同的编译器设置(例如调试与非调试)
此外,后处理类文件(混淆、AspectJ 等)通常会更改类文件。 如果您只是将相同的类文件用于运行时和分析,那么 JaCoCo 将运行良好。 所以创建这些类文件的工具链并不重要。
即使文件系统上的类文件相同,JaCoCo 运行时代理看到的类也可能不同。 这通常发生在在 JaCoCo 代理或特殊类加载器预处理类文件之前配置另一个 Java 代理时。 典型的候选人是:
同一页涵盖了可能的解决方案。
有哪些解决方法可以处理运行时修改的类?
如果在您的设置中的运行时类被修改,则有一些解决方法可以使 JaCoCo 无论如何工作:
编辑于 22-02-2017
如何使用离线仪器:使用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 需要与执行时使用的报告生成完全相同的类文件。 由于不同的编译器和/或其他修改类的工具,类可能会有所不同。
我注意到,如果您想要报告代码覆盖率的类在您的 JUnit 测试中被 Mockito 和 PowerMockito 抑制了其静态初始化,则会发生这种情况。 例如,如果您的测试类如下所示:
@SuppressStaticInitializationFor(
{"com.yourpkg.A",
"com.yourpkg.B"})
public class Test {
@Test
public void Test() { }
}
测试时的错误将类似于:
Classes in bundle 'yourProject' do not match with execution data.
For report generation the same class files must be used as at runtime.
Execution data for class com/yourpkg/A does not match.
Execution data for class com/yourpkg/B does not match.
具有深刻见解的各种答案,但在摆弄设置 2 天后,我仍然会分享对我有用的内容。
因此,根据代码设置指南,它说您需要在构建任务之后运行分析任务。 这是我完全遗漏的一步。
这是我的任务序列之前的样子
- task: Gradle@2
inputs:
gradleWrapperFile: 'gradlew'
tasks: '--build-cache jacocoTestReport SonarQube'
options: '-PversionName=$(Build.BuildNumber) -PversionCode=$(Build.BuildId) -Porg.gradle.parallel=true'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
javaHomeOption: 'JDKVersion'
jdkVersionOption: '1.11'
gradleOptions: '-Xmx4096m'
sonarQubeRunAnalysis: false
continueOnError: true
displayName: "Run Quality Scan and upload"
env:
SONAR_LOGIN: $(sonar-login)
BRANCH_NAME: $(Build.SourceBranchName)
- task: Gradle@2
condition: in(variables['Build.SourceBranchName'], 'develop')
inputs:
gradleWrapperFile: 'gradlew'
tasks: '--build-cache build publishAllPublicationsToMyDigitalRepository'
options: '-PversionName=$(Build.BuildNumber) -PversionCode=$(Build.BuildId) -PsecureSign'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
javaHomeOption: 'JDKVersion'
jdkVersionOption: '1.11'
gradleOptions: '-Xmx4096m'
sonarQubeRunAnalysis: false
env:
SDK_NAME: 'iphoneos'
continueOnError: false
displayName: "Build & publish library"
这是重新定位后的样子
- task: Gradle@2
condition: in(variables['Build.SourceBranchName'], 'develop')
inputs:
gradleWrapperFile: 'gradlew'
tasks: '--build-cache build publishAllPublicationsToMyDigitalRepository'
options: '-PversionName=$(Build.BuildNumber) -PversionCode=$(Build.BuildId) -PsecureSign'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
javaHomeOption: 'JDKVersion'
jdkVersionOption: '1.11'
gradleOptions: '-Xmx4096m'
sonarQubeRunAnalysis: false
env:
SDK_NAME: 'iphoneos'
continueOnError: false
displayName: "Build & publish library"
- task: Gradle@2
inputs:
gradleWrapperFile: 'gradlew'
tasks: '--build-cache jacocoTestReport SonarQube'
options: '-PversionName=$(Build.BuildNumber) -PversionCode=$(Build.BuildId) -Porg.gradle.parallel=true'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
javaHomeOption: 'JDKVersion'
jdkVersionOption: '1.11'
gradleOptions: '-Xmx4096m'
sonarQubeRunAnalysis: false
continueOnError: true
displayName: "Run Quality Scan and upload"
env:
SONAR_LOGIN: $(sonar-login)
BRANCH_NAME: $(Build.SourceBranchName)
所以本质上我学到了一些东西,在这里断章取义,但最重要的是。
添加离线检测后,覆盖范围是正确的,但我开始收到class is already instrumented消息。 在 build.gradle 中添加这个有帮助。
test {
jacoco {
excludes = ['{package_path}'] //package_path like '*com/**'
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.