背景:在每个模块library中的test文件夹下写的Junit单元测试不能统计覆盖率。必须将'com.android.library'更改为'com.android.application'方能统计此模块下的单元测试覆盖率。
为方便统计全局覆盖率,特此通过jacoco和脚本实现统计。
前期准备工作
1.全局统计jacoco-all.gradle
apply plugin: 'jacoco'
jacoco {
toolVersion = "0.8.7" //指定jacoco的版本
reportsDir = file("$buildDir/JacocoReport") //指定jacoco生成报告的文件夹
}
/*tasks.withType(Test) {
//jacoco.includeNoLocationClasses = true
jacoco.excludes = ['jdk.internal.*']
}*/
android {
defaultPublishConfig "debug"
buildTypes {
debug {
//打开覆盖率统计开关
testCoverageEnabled = true
}
}
testOptions {
unitTests.all {
jacoco {
includeNoLocationClasses = true
jacoco.excludes = ['jdk.internal.*']
}
}
unitTests {
includeAndroidResources = true
}
}
}
task jacocoTestReport(type: JacocoReport,dependsOn: ["testDebugUnitTest","createDebugCoverageReport"]) {
group = "Reporting"
reports {
xml.enabled = true
html.enabled = true
}
def fileFilter = ['**/R*.class',
'**/*$InjectAdapter.class',
'**/*$ModuleAdapter.class',
'**/*$ViewInjector*.class',
'**/*Binding*.class',
'**/*BR*.class'
]
def classDirectoriesFiles = files()
project.rootProject.allprojects.each { project ->
def debugTree = fileTree(
dir: "${project.projectDir}/build/intermediates/javac/debug/classes",
excludes: fileFilter)
def kotlinDebugTree = fileTree(
dir: "${project.projectDir}/build/tmp/kotlin-classes/debug")
classDirectoriesFiles.from.add(debugTree)
classDirectoriesFiles.from.add(kotlinDebugTree)
}
classDirectories.from = classDirectoriesFiles
def executionDataFiles = files()
project.rootProject.allprojects.each { project ->
def executionDataFile = file("${project.projectDir}/build/jacoco/testDebugUnitTest.exec")
if (executionDataFile.exists() || project.name == "app"){
executionDataFiles.from.add(executionDataFile)
}
}
executionData.from = executionDataFiles//指定报告数据的路径
}
2.单个Library统计jacoco.gradle
apply plugin: 'jacoco'
jacoco {
toolVersion = "0.8.7" //指定jacoco的版本
reportsDir = file("$buildDir/JacocoReport") //指定jacoco生成报告的文件夹
}
/*tasks.withType(Test) {
//jacoco.includeNoLocationClasses = true
jacoco.excludes = ['jdk.internal.*']
}*/
android {
defaultPublishConfig "debug"
buildTypes {
debug {
//打开覆盖率统计开关
testCoverageEnabled = true
}
}
testOptions {
unitTests.all {
jacoco {
includeNoLocationClasses = true
jacoco.excludes = ['jdk.internal.*']
}
}
unitTests {
includeAndroidResources = true
}
}
}
task jacocoTestReport(type: JacocoReport,dependsOn: ["testDebugUnitTest"]) {
//task jacocoTestReport(type: JacocoReport,dependsOn: ["createDebugCoverageReport"]) {
group = "Reporting"
reports {
xml.enabled = true
html.enabled = true
}
def fileFilter = ['**/R*.class',
'**/*$InjectAdapter.class',
'**/*$ModuleAdapter.class',
'**/*$ViewInjector*.class',
'**/*Binding*.class',
'**/*BR*.class'
]
def debugTree = fileTree(
dir: "${buildDir}/intermediates/javac/debug/classes",
excludes: fileFilter)
def kotlinDebugTree = fileTree(
dir: "${buildDir}/tmp/kotlin-classes/debug")
classDirectories.from = files(
debugTree, kotlinDebugTree
)
/*def debugTree = fileTree(
dir: "${buildDir}/intermediates/javac/debug/classes",
excludes: fileFilter)
classDirectories.from = files(
debugTree
)*/
/*def mainSrc = "${project.projectDir}/src/main/java" //指定源码目录
additionalSourceDirs.from = files([mainSrc])
sourceDirectories.from = files([mainSrc])*/
executionData.from = files("${buildDir}/jacoco/testDebugUnitTest.exec")//指定报告数据的路径
}
3.子模块配置jacoco-config.gradle
apply plugin: 'jacoco'
android {
defaultPublishConfig "debug"
buildTypes {
debug {
minifyEnabled false
testCoverageEnabled = true
}
coverageDebug {
minifyEnabled false
testCoverageEnabled true
}
}
}
4.gradle.properties 内自定义值
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
android.useAndroidX=true
android.enableJetifier=true
kotlin.code.style=official
#此处有几个Library要写几个对应的变量,默认要写成false
isLibCommonJacocoReport=false
上述四个文件都是放在应该的根目录下的
各模块gradle内的配置示例
1.主入口app内的build.gradle配置
plugins {
id 'com.android.application'
}
//此段一定要放在application下,否则会报错
apply from: rootProject.file('jacoco-all.gradle')
2.Library下的build.gradle配置,此处示例为lib/common目录
//根据isLibCommonJacocoReport变量值得更新将library替换成application生成当前模块的覆盖率
if (isLibCommonJacocoReport.toBoolean()){
apply plugin: 'com.android.application'
apply from: rootProject.file('jacoco.gradle')
}else {
apply plugin: 'com.android.library'
apply from: rootProject.file('jacoco-config.gradle')
}
单个模块做当前模块的覆盖率统计操作
执行命名行:gradlew lib:common:jacocoTestReport -PisLibCommonJacocoReport="true"
上面的lib:commons是library的目录,PisLibCommonJacocoReport是给isLibCommonJacocoReport赋值为true
统计所有模块的覆盖率,并合成到app下
实现的原理:将所有子Library下的单元测试覆盖率全部统计完成会生成当前模块的的testDebugUnitTest.exec文件,然后使用上述文件的所有集合最后执行app的覆盖率统计
统计脚本
@echo off
gradlew lib:common:jacocoTestReport -PisLibCommonJacocoReport="true" && gradlew app:jacocoTestReport
pause
gradlew lib:common:jacocoTestReport -PisLibCommonJacocoReport="true"是统计当前library的覆盖率命令
注:不同模块要使用对应的变量名-isLibCommonJacocoReport,命令执行路径也要对
gradlew app:jacocoTestReport是将所有的testDebugUnitTest.exe集合处理
缺点:非常明显的统计时长过长
大家有什么好的处理方案欢迎给出,感谢。








网友评论