Android库模块Jacoco失效,coverage.ec文件始终为空
问题
我在类似NowInAndroid的多模块Android项目中配置Jacoco,所用的Jacoco.kt、AndroidApplicationJacocoConventionPlugin和AndroidLibraryJacocoConventionPlugin配置均与NowInAndroid项目一致。运行app模块的androidTest时,coverage.ec文件能正常生成;但运行库模块的androidTest时,生成的coverage.ec文件为空,求解决办法。
配置代码如下:
private val coverageExclusions = listOf( // Android "**/R.class", "**/R\$*.class", "**/BuildConfig.*", "**/Manifest*.*", "**/*_Hilt*.class", "**/Hilt_*.class", ) private fun String.capitalize() = replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() } internal fun Project.configureJacoco( androidComponentsExtension: AndroidComponentsExtension<*, *, *> ) { configure<JacocoPluginExtension> { toolVersion = "0.8.7" } androidComponentsExtension.onVariants { variant -> val myObjFactory = project.objects val buildDir = layout.buildDirectory.get().asFile val allJars: ListProperty<RegularFile> = myObjFactory.listProperty(RegularFile::class.java) val allDirectories: ListProperty<Directory> = myObjFactory.listProperty(Directory::class.java) val reportTask = tasks.register("create${variant.name.capitalize()}CombinedCoverageReport", JacocoReport::class) { classDirectories.setFrom( allJars, allDirectories.map { dirs -> dirs.map { dir -> myObjFactory.fileTree().setDir(dir).exclude(coverageExclusions) } } ) reports { xml.required.set(true) html.required.set(true) } // TODO: This is missing files in src/debug/, src/prod, src/demo, src/demoDebug... sourceDirectories.setFrom(files("$projectDir/src/main")) println("This is the projectDir -> ${projectDir}") executionData.setFrom( project.fileTree("$buildDir/outputs/unit_test_code_coverage/${variant.name}UnitTest") .matching { include("**/*.exec") }, project.fileTree("$buildDir/outputs/code_coverage/${variant.name}AndroidTest") .matching { include("**/*.ec") } ) } variant.artifacts.forScope(ScopedArtifacts.Scope.PROJECT) .use(reportTask) .toGet( ScopedArtifact.CLASSES, { _ -> allJars }, { _ -> allDirectories }, ) } tasks.withType<Test>().configureEach { configure<JacocoTaskExtension> { // Required for JaCoCo + Robolectric // https://github.com/robolectric/robolectric/issues/2230 isIncludeNoLocationClasses = true // Required for JDK 11 with the above // https://github.com/gradle/gradle/issues/5184#issuecomment-391982009 excludes = listOf("jdk.internal.*") } } }
解决方案
开启库模块的AndroidTest覆盖率收集
库模块默认可能未启用AndroidTest代码覆盖率,需在库模块的build.gradle.kts中显式配置:android { buildTypes { named("debug") { enableAndroidTestCoverage = true } } }修正覆盖率文件路径匹配规则
库模块的coverage.ec文件可能存储在子目录中,调整executionData的匹配范围,确保能找到文件:executionData.setFrom( project.fileTree("$buildDir/outputs/unit_test_code_coverage/${variant.name}UnitTest") .matching { include("**/*.exec") }, project.fileTree("$buildDir/outputs/code_coverage/${variant.name}AndroidTest") .matching { include("**/**coverage.ec") } // 匹配所有子目录下的.ec文件 )确认库模块的Jacoco插件配置生效
检查库模块的ConventionPlugin是否正确应用Jacoco插件并调用配置方法:class AndroidLibraryJacocoConventionPlugin : Plugin<Project> { override fun apply(target: Project) { with(target) { pluginManager.apply("jacoco") val androidComponents = extensions.getByType(AndroidComponentsExtension::class.java) configureJacoco(androidComponents) } } }升级Jacoco版本
当前使用的0.8.7版本较旧,可能与新版AGP存在兼容性问题,尝试升级到稳定新版本:configure<JacocoPluginExtension> { toolVersion = "0.8.12" }验证测试用例是否实际执行
运行库模块AndroidTest任务时,确认测试用例已正常执行——若测试未运行,自然不会生成有效覆盖率数据,可通过测试日志或添加打印语句验证。
内容的提问来源于stack exchange,提问作者Júnio Farias
相关产品推荐
相关产品推荐

