如何用Android Gradle插件生成单元测试JaCoCo XML覆盖率报告?
解决方案:Android单元测试JaCoCo XML覆盖率报告配置(多产品风味)
一、优先使用AGP内置支持(避免触发仪器化测试)
AGP 7.0+已经将单元测试和仪器化测试的覆盖率配置拆分,只要正确使用enableUnitTestCoverage,就不会触发connectedAndroidTest:
- 修改
app/build.gradle(Groovy)中的buildType配置:
android { buildTypes { debug { // 仅开启单元测试覆盖率,不会触发仪器化测试任务 enableUnitTestCoverage true } } // 保留你的5个产品风味配置 productFlavors { flavor1 {} flavor2 {} flavor3 {} flavor4 {} flavor5 {} } }
- 生成单个风味的XML报告
AGP会自动为每个风味+debug构建类型生成专属的单元测试覆盖率任务,比如:
./gradlew createFlavor1DebugUnitTestCoverageReport
执行后,XML报告默认生成在:app/build/reports/coverage/flavor1DebugUnitTest/coverage.xml
- 一次性生成所有风味的报告
添加自定义任务批量执行所有风味的覆盖率任务:
task createAllUnitTestCoverageReports { dependsOn android.productFlavors.collect { flavor -> "create${flavor.name.capitalize()}DebugUnitTestCoverageReport" } }
运行命令:
./gradlew createAllUnitTestCoverageReports
二、手动配置JaCoCo(更灵活的场景)
如果需要自定义排除规则、报告路径等,可手动配置,但必须关闭AGP内置支持避免冲突:
- 关闭AGP内置覆盖率并引入JaCoCo插件
android { buildTypes { debug { // 关闭AGP内置支持,防止冲突 enableUnitTestCoverage false } } } plugins { id 'jacoco' } jacoco { // 使用与AGP兼容的版本(AGP 8.x推荐0.8.10+) toolVersion = "0.8.10" }
- 为每个风味创建自定义JaCoCo报告任务
android.productFlavors.each { flavor -> def buildType = 'debug' def variantName = "${flavor.name}${buildType.capitalize()}" def testTaskName = "test${variantName}UnitTest" task "jacoco${variantName}UnitTestReport"(type: JacocoReport) { dependsOn testTaskName // 排除无需统计的类 classDirectories.setFrom(fileTree(dir: "${project.buildDir}/intermediates/javac/${variantName}/classes", excludes: [ '**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*' ])) // 指定单元测试生成的.exec文件路径 executionData.setFrom(file("${project.buildDir}/outputs/unit_test_code_coverage/${variantName}/unitTest/${testTaskName}.exec")) // 指定源代码路径(包含主代码和风味专属代码) sourceDirectories.setFrom(fileTree(dir: "src/main/java") + fileTree(dir: "src/main/kotlin")) additionalSourceDirs.setFrom(fileTree(dir: "src/${flavor.name}/java") + fileTree(dir: "src/${flavor.name}/kotlin")) // 输出XML格式报告 reports { xml.required.set(true) xml.outputLocation.set(file("${project.buildDir}/reports/jacoco/${variantName}UnitTest/coverage.xml")) html.required.set(false) // 不需要HTML可关闭 } } } // 批量生成所有风味报告的任务 task createAllJaCoCoUnitTestReports { dependsOn android.productFlavors.collect { flavor -> "jacoco${flavor.name.capitalize()}DebugUnitTestReport" } }
三、避免配置冲突的关键
- 二选一原则:不要同时开启AGP的
enableUnitTestCoverage和手动配置JaCoCo,必须关闭其中一个。 - 版本兼容:手动配置时,确保JaCoCo工具版本与当前AGP版本匹配(可查看AGP官方文档确认兼容版本)。
- 路径动态化:避免硬编码文件路径,使用
project.buildDir等Gradle内置变量动态获取,适配不同AGP版本的路径变化。
内容的提问来源于stack exchange,提问作者bisgardo
相关产品推荐
相关产品推荐

