Gradle托管设备结合Jacoco生成代码覆盖率的问题咨询
Gradle托管设备与Jacoco结合获取代码覆盖率的可行方案
针对库模块使用Gradle托管设备时Jacoco覆盖率报告的时序问题,以下是几种实用解决方案:
方案1:修改默认Coverage任务的依赖
直接调整createDebugCoverageReport的依赖关系,替换默认的connectedDebugAndroidTest为你的Gradle托管设备测试任务(如pixel2DebugAndroidTest),确保覆盖率任务等待托管设备测试完成后再执行:
Groovy DSL(模块build.gradle)
tasks.named('createDebugCoverageReport') { // 添加托管设备测试任务依赖 dependsOn 'pixel2DebugAndroidTest' // 移除原有默认依赖(可选,若mustRunAfter已能保证时序可省略) dependencies.removeAll { it.name == 'connectedDebugAndroidTest' } // 强制在托管设备测试完成后执行 mustRunAfter 'pixel2DebugAndroidTest' }
Kotlin DSL(模块build.gradle.kts)
tasks.named("createDebugCoverageReport") { dependsOn("pixel2DebugAndroidTest") dependencies.removeIf { it.name == "connectedDebugAndroidTest" } mustRunAfter("pixel2DebugAndroidTest") }
执行命令:./gradlew createDebugCoverageReport
方案2:为托管设备创建专属Coverage任务
如果不想修改默认任务,可单独为Gradle托管设备创建自定义覆盖率报告任务,配置更灵活:
Groovy DSL(模块build.gradle)
task pixel2DebugCoverageReport(type: JacocoReport) { // 配置源码路径 sourceDirectories.setFrom(fileTree(dir: 'src/main/java')) // 配置class文件路径,排除无关文件 classDirectories.setFrom(fileTree(dir: 'build/intermediates/javac/debug/classes') { exclude '**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*' }) // 配置Jacoco执行数据文件路径(对应托管设备测试生成的exec文件) executionData.setFrom(fileTree(dir: 'build/outputs/code_coverage/pixel2DebugAndroidTest/connected') { include '*.exec' }) // 依赖托管设备测试任务 dependsOn 'pixel2DebugAndroidTest' }
Kotlin DSL(模块build.gradle.kts)
tasks.register<JacocoReport>("pixel2DebugCoverageReport") { sourceDirectories.setFrom(fileTree("src/main/java")) classDirectories.setFrom(fileTree("build/intermediates/javac/debug/classes") { exclude("**/R.class", "**/R$*.class", "**/BuildConfig.*", "**/Manifest*.*") }) executionData.setFrom(fileTree("build/outputs/code_coverage/pixel2DebugAndroidTest/connected") { include("*.exec") }) dependsOn("pixel2DebugAndroidTest") }
执行命令:./gradlew pixel2DebugCoverageReport
方案3:全局统一配置依赖(多设备场景)
如果有多个Gradle托管设备测试任务,可在项目根目录的构建脚本中全局配置,让所有Coverage任务自动关联对应的托管设备测试任务:
Groovy DSL(根build.gradle)
subprojects { afterEvaluate { tasks.withType(JacocoReport).configureEach { // 按命名规则匹配对应的托管设备测试任务 def deviceTestTaskName = name.replace('CoverageReport', 'AndroidTest') def deviceTestTask = tasks.findByName(deviceTestTaskName) if (deviceTestTask) { dependsOn deviceTestTask mustRunAfter deviceTestTask // 移除默认的connected测试依赖 dependencies.removeAll { it.name.startsWith('connected') } } } } }
Kotlin DSL(根build.gradle.kts)
subprojects { afterEvaluate { tasks.withType<JacocoReport>().configureEach { val deviceTestTaskName = name.replace("CoverageReport", "AndroidTest") tasks.findByName(deviceTestTaskName)?.let { dependsOn(it) mustRunAfter(it) dependencies.removeIf { dep -> dep.name.startsWith("connected") } } } } }
必要前置配置
确保库模块已启用Jacoco和测试覆盖率:
android { buildTypes { debug { testCoverageEnabled true } } } jacoco { toolVersion = "0.8.10" // 使用最新稳定版本 }
内容的提问来源于stack exchange,提问作者johngray1965
相关产品推荐
相关产品推荐

