java Kotlin JaCoCo IllegalClassFormatException。请提供原始的非仪器类
我正在尝试获取Android应用程序模块的测试覆盖率报告,并执行testVariantBuildTypeUnitTest任务
尽管所有测试都通过了,测试classNameTest。xml文件包含以下错误消息。此错误仅适用于包含来自Kotlin的Java调用的方法。这个问题有什么解决办法吗
**Caused by: java.lang.IllegalStateException: Cannot process instrumented class... Please supply original non-instrumented classes.
at org.jacoco.agent.rt.internal_f3994fa.core.internal.instr.InstrSupport.assertNotInstrumented(InstrSupport.java:238)
at org.jacoco.agent.rt.internal_f3994fa.core.internal.instr.ClassInstrumenter.visitField(ClassInstrumenter.java:56)
at org.jacoco.agent.rt.internal_f3994fa.asm.ClassVisitor.visitField(ClassVisitor.java:339)
at org.jacoco.agent.rt.internal_f3994fa.asm.ClassReader.readField(ClassReader.java:1111)
at org.jacoco.agent.rt.internal_f3994fa.asm.ClassReader.accept(ClassReader.java:713)
at org.jacoco.agent.rt.internal_f3994fa.asm.ClassReader.accept(ClassReader.java:401)
at org.jacoco.agent.rt.internal_f3994fa.core.instr.Instrumenter.instrument(Instrumenter.java:90)
at org.jacoco.agent.rt.internal_f3994fa.core.instr.Instrumenter.instrument(Instrumenter.java:108)
我们有多模块安卓项目,因此我们使用此自定义Jacoco任务获取覆盖率报告:
project.afterEvaluate {
(安卓.hasProperty('applicationVariants')
? 安卓.'applicationVariants'
: 安卓.'libraryVariants')
.all { variant ->
def variantName = variant.name
def unitTestTask = "test${variantName.capitalize()}UnitTest"
def jacocoReportName = unitTestTask + project.name
tasks.create(name: jacocoReportName, type: JacocoReport, dependsOn: [
"$unitTestTask"
]) {
group = "Reporting"
description = "Generate Jacoco coverage reports for the ${variantName.capitalize()} build"
reports {
html.enabled = true
xml.enabled = true
}
def fileFilter = [
// data binding
'安卓/databinding/**/*.class',
'**/安卓/databinding/*Binding.class',
'**/安卓/databinding/*',
'**/安卓x/databinding/*',
'**/databinding',
'**/BR.*',
// 安卓
'**/R.class',
'**/R$*.class',
'**/BuildConfig.*',
'**/Manifest*.*',
'**/*Test*.*'
]
def javaClasses = fileTree(dir: variant.javaCompileProvider.get().destinationDir,
excludes: fileFilter)
def kotlinClasses = fileTree(dir: "${buildDir}/tmp/kotlin-classes/${variantName}",
excludes: fileFilter)
classDirectories.setFrom(files([
javaClasses,
kotlinClasses
]))
def variantSourceSets = variant.sourceSets.java.srcDirs.collect { it.path }.flatten()
sourceDirectories.setFrom(project.files(variantSourceSets))
if (isAndroidLibrary(project)) {
executionData(files([
"${projectDir}/jacoco.exec"
]))
}else{
executionData(files([
"$project.buildDir/jacoco/${project.name}.exec"
]))
}
}
}
}
问候,
# 1 楼答案
解决方案
问题很可能存在于您的模块级构建中。gradle文件。您需要删除testCoverageEnabled或将其设置为false
解释和参考资料首先,我与JaCoCo多年来一直在努力解决android上的单元测试覆盖问题,并且在AGP(android Gradle插件)团队增强AGP(例如Similar issue)时多次遇到这些问题,因此该解决方案可能会在未来的AGP版本中发生变化
在AGP4.1的release中,AGP团队改变了插件处理单元测试的方式。我向AGP团队提出了一个enter link description here问题,他们解释说插件(AGP4.1+)使用自己的工具形式来获得覆盖,这无疑与JaCoCo不兼容。正是在这个问题上,我强调了解决方案
注1:此问题在DSL文档中有not documented
注2:还应注意的是,在我编写本AGP7时,同样的问题也出现在开发中
注意事项
此解决方案将导致生成插装测试覆盖率时出现问题,因为AGP生成插装测试覆盖率(以.ec文件的形式),这意味着要获得插装测试覆盖率,您必须具有
testCoverageEnabled true
。 作为解决办法,您可以:请注意,这是唯一有效的,当这个答案是书面的,希望谷歌将解决这个问题在未来