Android Library模块中Jacoco/CodeCov无法识别单元测试的问题咨询
我之前在配置Android Library模块的Jacoco时也碰到过完全一样的情况——任务能正常执行,但就是看不到单元测试的覆盖率数据,仿佛测试根本没跑。这是因为Library模块的AGP构建路径和Application模块存在几个关键差异,你的配置需要针对这些差异调整:
1. 修正类文件的扫描路径
AGP 4.0+版本之后,Java和Kotlin的编译产物路径分开了,不再统一放在intermediates/classes/debug下。你需要同时扫描Java和Kotlin的类文件目录:
def debugTree = fileTree(dir: "${buildDir}/intermediates/javac/debug", excludes: fileFilter) + fileTree(dir: "${buildDir}/intermediates/kotlin-classes/debug", excludes: fileFilter)
原来的路径只覆盖了旧版AGP的Java类文件位置,漏掉了Kotlin编译后的类,导致Jacoco找不到要分析的代码主体。
2. 调整源代码路径
如果你的Library模块包含Kotlin代码,别忘了把Kotlin源码目录加入sourceDirectories:
def mainSrc = files("${project.projectDir}/src/main/java", "${project.projectDir}/src/main/kotlin")
只指定src/main/java会导致Kotlin代码的覆盖率完全无法被统计。
3. 优化执行数据的路径
Library模块的单元测试执行数据(.exec文件)存放位置可能和Application模块略有不同,同时如果不需要Instrumented测试,可以去掉对createDebugCoverageReport的依赖(这个任务是针对设备/模拟器测试的):
task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest']) { reports { xml.enabled = true html.enabled = true } def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*'] def debugTree = fileTree(dir: "${buildDir}/intermediates/javac/debug", excludes: fileFilter) + fileTree(dir: "${buildDir}/intermediates/kotlin-classes/debug", excludes: fileFilter) def mainSrc = files("${project.projectDir}/src/main/java", "${project.projectDir}/src/main/kotlin") sourceDirectories.setFrom(mainSrc) classDirectories.setFrom(debugTree) executionData.setFrom(fileTree(dir: "$buildDir", includes: [ "jacoco/testDebugUnitTest.exec", "outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec" ])) }
多添加一个outputs/unit_test_code_coverage/...路径是为了兼容不同AGP版本的存放位置,确保能精准找到单元测试的执行记录。
验证步骤
在运行Jacoco任务之前,先手动执行单元测试确认测试本身能正常运行:
./gradlew :library_video:testDebugUnitTest
如果测试能正常跑完,再执行Jacoco报告任务:
./gradlew :library_video:jacocoTestReport
之后你就能在library_video/build/reports/jacoco/jacocoTestReport/html目录下看到包含所有单元测试覆盖率的完整报告了。
内容的提问来源于stack exchange,提问作者Olitron

