AGP 7.2.x及后续版本Jacoco代码覆盖率异常偏低求助
AGP 7.2+版本Jacoco代码覆盖率骤降问题排查与解决方案
问题背景
自AGP 7.2.0-alpha01及后续版本(含7.2.0、7.3.x、7.4.x预览版)起,即便Jacoco配置符合预期,代码覆盖率也会异常骤降。在AGP 7.1.3版本中覆盖率能达到90%以上,切换到更高版本后直接掉到10%以下,多数类被标记为未覆盖,且没有明显规律——不管是插桩测试还是常规单元测试覆盖的类,都存在数据缺失,只有少量类的覆盖率数据正常显示。
你的Jacoco任务配置如下:
task developDebugCodeCoverageReport(type: JacocoReport, dependsOn: ['testDevelopDebugUnitTest', 'createDevelopDebugCoverageReport']) { group = 'Code Coverage' description = 'Generate Jacoco coverage reports for the developDebug build' reports { html.required.set(true) xml.required.set(true) } def excludes = [ // list of files I want to exclude ] def javaClasses = fileTree(dir: "${buildDir}/intermediates/javac/developDebug/classes", excludes: excludes) def kotlinClasses = fileTree(dir: "${buildDir}/tmp/kotlin-classes/developDebug", excludes: excludes) classDirectories.setFrom(files([ javaClasses, kotlinClasses ])) sourceDirectories.setFrom("${project.projectDir}/src/main/java") def junitTestsData = "${buildDir}/outputs/unit_test_code_coverage/developDebugUnitTest/testDevelopDebugUnitTest.exec" def androidTestsData = fileTree(dir: "${buildDir}/outputs/code_coverage/developDebugAndroidTest/connected/", includes: ["**/*.ec"]) executionData.setFrom(files([ junitTestsData, androidTestsData ])) }
排查思路
- 核对AGP版本带来的路径变更:AGP 7.2+调整了编译产物的存放路径,比如Kotlin类文件从
tmp/kotlin-classes移到了intermediates/kotlin-classes,旧配置读错路径会导致大量Kotlin类没被统计。另外单元测试的覆盖率数据路径也可能变了,得确认.exec/.ec文件的实际位置。 - 验证类文件路径是否正确:手动打开
build目录,看看Java和Kotlin编译后的class文件是不是在你配置的路径里,别光看配置想当然。 - 检查Jacoco版本兼容性:AGP 7.2+对Jacoco版本有要求,比如AGP 7.2.x要配Jacoco 0.8.7以上,AGP 7.3+配0.8.8以上,版本不匹配会导致覆盖率数据读不出来。
- 解析执行文件看数据:用Jacoco的CLI工具解析
.exec和.ec文件,看看里面有没有预期的覆盖数据。比如跑这个命令:
对比AGP 7.1.3和新版本生成的文件内容,确认是不是真的有数据缺失。java -jar jacoco-cli-0.8.8.jar report testDevelopDebugUnitTest.exec --classfiles path/to/your/classes --html report-output
修复方案
1. 修正Class文件路径
把Kotlin类文件路径改成AGP 7.2+的标准路径:
def javaClasses = fileTree(dir: "${buildDir}/intermediates/javac/developDebug/classes", excludes: excludes) // 替换旧的tmp路径 def kotlinClasses = fileTree(dir: "${buildDir}/intermediates/kotlin-classes/developDebug", excludes: excludes) classDirectories.setFrom(files([javaClasses, kotlinClasses]))
2. 调整单元测试执行数据路径
AGP 7.2+里单元测试的.exec文件路径可能变了,改成动态匹配:
def junitTestsData = fileTree(dir: "${buildDir}/outputs/unit_test_code_coverage/developDebugUnitTest", includes: ["*.ec", "*.exec"])
3. 匹配Jacoco版本
在根项目的build.gradle里指定兼容的Jacoco版本:
buildscript { dependencies { classpath 'org.jacoco:org.jacoco.core:0.8.8' // 适配AGP 7.2+ } }
4. 改用AGP内置的Jacoco支持(推荐)
别自己写自定义任务了,用AGP自带的机制更稳:
android { buildTypes { debug { testCoverageEnabled true } } }
之后直接跑命令生成报告:
./gradlew createDevelopDebugCoverageReport testDevelopDebugUnitTestCoverageReport
5. 排除未插桩的类
把那些不需要统计的类排除掉,比如R类、BuildConfig类:
def excludes = [ '**/R.class', '**/R$*.class', '**/BuildConfig.class', '**/Manifest*.*' ]
内容的提问来源于stack exchange,提问作者Zach
相关产品推荐
相关产品推荐

