Android项目集成Jacoco后无法生成代码覆盖率报告
Jacoco覆盖率报告未生成的排查与修复
核心排查点与修复方案
1. 确认自定义Jacoco任务已手动执行
你的配置注册了Jacoco{VariantName}CodeCoverage格式的自定义任务(比如JacocoDebugCodeCoverage),Android Studio不会自动执行该任务,必须手动触发:
- 打开右侧边栏的Gradle面板
- 找到项目 →
Tasks→Reporting→ 双击对应变体的Jacoco任务(如JacocoDebugCodeCoverage)执行
2. 适配AGP 7+的编译类目录路径
你的classDirectories配置路径在AGP 7及以上版本失效,编译后Java/Kotlin类的目录结构已变更:
- Java类目录需指定具体变体(如
debug):intermediates/javac/{variantName} - Kotlin类目录从
tmp/kotlin-classes/改为intermediates/kotlin-classes/{variantName}
修正后的classDirectories配置:
classDirectories.setFrom(files( fileTree(dir: layout.buildDirectory.dir("intermediates/javac/${variantName}")) { exclude "**/R.class", "**/R\$*.class", "**/BuildConfig.*", "**/Manifest*.*", "**/*Test*.*" }, fileTree(dir: layout.buildDirectory.dir("intermediates/kotlin-classes/${variantName}")) { exclude "**/R.class", "**/R\$*.class", "**/BuildConfig.*", "**/Manifest*.*", "**/*Test*.*" } ))
3. 精准定位测试执行数据文件
过宽的文件匹配可能读取无效数据,建议直接指定单元测试和UI测试的执行文件路径:
executionData.setFrom(files( // 单元测试执行数据 layout.buildDirectory.dir("outputs/unit_test_code_coverage/${variantName}UnitTest/test${variantName}UnitTest.exec"), // UI测试执行数据 layout.buildDirectory.dir("outputs/code_coverage/${variantName}AndroidTest/connected/*coverage.ec") ))
4. 移除已弃用的配置项
AGP 4.1+中enableAndroidTestCoverage和enableUnitTestCoverage已被弃用,仅保留testCoverageEnabled即可:
debug { testCoverageEnabled = true }
5. 验证测试任务执行状态
如果单元测试或UI测试执行失败,Jacoco无法生成有效执行数据:
- 先单独运行
testDebugUnitTest和connectedDebugAndroidTest任务,确认所有测试通过 - 检查测试控制台输出,排除测试报错、设备连接失败等问题
修正后的完整配置示例
apply plugin: 'jacoco' android { buildTypes { debug { testCoverageEnabled = true } } applicationVariants.configureEach { variant -> def variantName = variant.name.capitalize() def unitTests = "test${variantName}UnitTest" def androidTests = "connected${variantName}AndroidTest" tasks.register("Jacoco${variantName}CodeCoverage", JacocoReport) { dependsOn(unitTests, androidTests) group = "Reporting" description = "执行UI和单元测试,生成并合并Jacoco覆盖率报告" reports { xml.required = true xml.outputLocation = layout.buildDirectory.file("jacoco/xml/${variantName}Coverage.xml") html.required = true html.outputLocation = layout.buildDirectory.dir("jacoco/html/${variantName}Coverage.html") } sourceDirectories.setFrom(layout.projectDirectory.dir("src/main")) classDirectories.setFrom(files( fileTree(dir: layout.buildDirectory.dir("intermediates/javac/${variantName}")) { exclude "**/R.class", "**/R\$*.class", "**/BuildConfig.*", "**/Manifest*.*", "**/*Test*.*" }, fileTree(dir: layout.buildDirectory.dir("intermediates/kotlin-classes/${variantName}")) { exclude "**/R.class", "**/R\$*.class", "**/BuildConfig.*", "**/Manifest*.*", "**/*Test*.*" } )) executionData.setFrom(files( layout.buildDirectory.dir("outputs/unit_test_code_coverage/${variantName}UnitTest/test${variantName}UnitTest.exec"), layout.buildDirectory.dir("outputs/code_coverage/${variantName}AndroidTest/connected/*coverage.ec") )) } } } jacoco { toolVersion = "0.8.8" } tasks.withType(Test).configureEach { jacoco { excludes = [ "**/R.class", "**/R\$*.class", "**/BuildConfig.*", "**/Manifest*.*", "**/*Test*.*" ] } }
执行修正后的配置后,重新运行对应变体的Jacoco任务,报告会生成在build/jacoco/html/{VariantName}Coverage.html路径下,直接打开该HTML文件即可查看覆盖率详情。
内容的提问来源于stack exchange,提问作者kgsharathkumar
相关产品推荐
相关产品推荐

