多模块Android Gradle Kotlin项目配置Jacoco遇问题求助
Android多模块项目配置Jacoco常见问题解决
问题根源
Android项目的test和jacocoTestReport任务是模块级任务,仅存在于Android应用/库模块(app、module1、module2)中,根项目本身没有这些任务。你在根build.gradle.kts里直接配置tasks.test和tasks.jacocoTestReport,Gradle找不到对应任务,因此报错。
另外,你在根项目直接应用jacoco插件,但未给具体模块启用,模块里不会自动生成Jacoco相关任务,导致执行jacocoTestReport时提示任务不存在。
正确配置步骤
1. 根项目全局引入Jacoco插件
修改根目录build.gradle.kts,将Jacoco插件标记为apply false,让子模块可以按需应用:
plugins { id(Dependencies.Plugins.androidApplication) version Dependencies.Versions.androidAppplication apply false id(Dependencies.Plugins.androidLibrary) version Dependencies.Versions.androidLibrary apply false id(Dependencies.Plugins.hilt) version Dependencies.Versions.hilt apply false id(Dependencies.Plugins.openApi) version Dependencies.Versions.openApi id(Dependencies.Plugins.kotlinAndroid) version Dependencies.Versions.kotlinAndroid apply false id(Dependencies.Plugins.sonarqube) version Dependencies.Versions.sonarqube id("jacoco") version "0.8.11" apply false // 替换为你需要的Jacoco版本 }
2. 批量配置所有Android模块的Jacoco
在根build.gradle.kts末尾添加批量配置逻辑,避免每个模块重复写代码:
subprojects { // 仅对Android应用/库模块生效 plugins.withId("com.android.application") { apply(plugin = "jacoco") configureJacocoForAndroid() } plugins.withId("com.android.library") { apply(plugin = "jacoco") configureJacocoForAndroid() } } // 提取公共配置函数 fun Project.configureJacocoForAndroid() { val android = extensions.getByName<com.android.build.gradle.BaseExtension>("android") android.buildTypes { getByName("debug") { enableUnitTestCoverage = true // 开启单元测试覆盖率收集 } } tasks.withType<Test> { finalizedBy("jacocoTestReportDebug") // 测试完成后自动生成Debug版本覆盖率报告 } tasks.register<JacocoReport>("jacocoTestReportDebug") { dependsOn(tasks.withType<Test>()) // 依赖所有测试任务 // 配置覆盖率数据来源 executionData.setFrom(fileTree(project.buildDir) { include("jacoco/testDebugUnitTest.exec") }) // 配置要分析的代码(源文件) sourceDirectories.setFrom(files(android.sourceSets.getByName("main").java.srcDirs)) classDirectories.setFrom(files(android.sourceSets.getByName("main").java.srcDirs) { exclude("**/R.class", "**/R$*.class", "**/BuildConfig.*", "**/Manifest*.*") }) // 报告输出配置 reports { html.required.set(true) // 生成可视化HTML报告 xml.required.set(true) // 生成供SonarQube使用的XML报告 csv.required.set(false) } } }
3. 执行命令生成报告
现在可以执行以下命令,生成所有模块的Debug版本单元测试覆盖率报告:
./gradlew testDebugUnitTest jacocoTestReportDebug
每个模块的报告会生成在模块目录/build/reports/jacoco/jacocoTestReportDebug/html路径下。
4. (可选)根项目聚合所有模块的覆盖率报告
如果需要统一的汇总报告,在根build.gradle.kts添加聚合任务:
tasks.register<JacocoReport>("jacocoRootReport") { dependsOn(subprojects.map { it.tasks.withType<Test>() }) executionData.setFrom(subprojects.map { fileTree(it.buildDir) { include("jacoco/testDebugUnitTest.exec") } }) sourceDirectories.setFrom(subprojects.map { it.extensions.getByName<com.android.build.gradle.BaseExtension>("android").sourceSets.getByName("main").java.srcDirs }) classDirectories.setFrom(subprojects.map { fileTree(it.extensions.getByName<com.android.build.gradle.BaseExtension>("android").sourceSets.getByName("main").java.srcDirs) { exclude("**/R.class", "**/R$*.class", "**/BuildConfig.*", "**/Manifest*.*") } }) reports { html.required.set(true) xml.required.set(true) html.outputLocation.set(file("$buildDir/reports/jacoco/root/html")) } }
执行命令生成汇总报告:
./gradlew testDebugUnitTest jacocoRootReport
Android与Spring Boot配置的关键差异
- Android项目的测试任务按BuildType区分(如
testDebugUnitTest、testReleaseUnitTest),没有通用的test任务 - Jacoco插件需要在每个Android模块中单独应用,根项目仅做全局引入
- 必须开启
enableUnitTestCoverage = true才能收集覆盖率数据
内容的提问来源于stack exchange,提问作者Petra Barus
相关产品推荐
相关产品推荐

