Jacoco 无法读取 .ec 文件
Jacoco can't read .ec file
为了为单元和 Ui 测试生成代码覆盖率,我已经实现了这个 jacoco.gradle
script
apply plugin: 'jacoco'
jacoco {
toolVersion = "0.8.5"
}
tasks.withType(Test) {
jacoco.includeNoLocationClasses = true
}
project.afterEvaluate {
android.applicationVariants.all { variant ->
def variantName = variant.name
def testTaskName = "test${variantName.capitalize()}UnitTest"
def uiTestCoverageTaskName = "create${variantName.capitalize()}CoverageReport"
tasks.create(
name: "${testTaskName}Coverage",
type: JacocoReport,
dependsOn: ["$testTaskName", "$uiTestCoverageTaskName"]) {
group = "Reporting"
description = "Generate Jacoco coverage reports for the ${variantName.capitalize()} build."
reports {
html.enabled = true
xml.enabled = true
}
def excludes = [
'**/R.class',
'**/R$*.class',
'**/BuildConfig.*',
'**/Manifest*.*',
'**/*Test*.*',
'android/**/*.*',
'**/*Application*.*',
'**/*Dagger*.*',
'**/*Hilt*.*',
'**/*GeneratedInjectorModuleDeps*.*'
]
def javaClasses = fileTree(dir: variant.javaCompiler.destinationDir, excludes: excludes)
def kotlinClasses = fileTree(dir: "${buildDir}/tmp/kotlin-classes/${variantName}", excludes: excludes)
classDirectories.setFrom(files([javaClasses, kotlinClasses]))
sourceDirectories.setFrom(
files([
"$project.projectDir/src/main/java",
"$project.projectDir/src/${variantName}/java",
"$project.projectDir/src/main/kotlin",
"$project.projectDir/src/${variantName}/kotlin"
]))
executionData.setFrom(
files([
"${project.buildDir}/jacoco/${testTaskName}.exec",
"${project.buildDir}/outputs/code_coverage/${variantName}AndroidTest/connected/*coverage.ec"
])
)
}
}
}
我在我的 app.build 中应用了这个脚本,就像这样 apply from: 'buildscripts/jacoco.gradle'
此任务可以生成一个单元和 ui 特定风格的测试覆盖率。
但是,当我使用 ./gradlew testDebugUnitTestCoverage
启动 gradle 任务时,测试执行正常,但在收集 UI 测试覆盖率时,我收到此错误:
Unable to read execution data file /.../app/build/outputs/code_coverage/debugAndroidTest/connected/*coverage.ec
我的项目层次结构如下所示
我正在使用 Gradle 6.1.1 和 Android Gradle Build 工具 4.0.0
在以前的版本中,文件名只是 coverage.ec
,因此通配符查找可以毫无问题地找到该文件。还有一些设备提供的模型不包含空格,这些也很好。
您 运行 的原因是 name/model 设备名称中包含空格。 “*coverage.ec”的通配符查找无法正确解析包含空格的文件名。
仍然可以抓取文件,只是需要多做一些工作。
换出:
executionData.setFrom(
files([
"${project.buildDir}/jacoco/${testTaskName}.exec",
"${project.buildDir}/outputs/code_coverage/${variantName}AndroidTest/connected/*coverage.ec"
])
)
//Set your UnitTest .exec file
executionData.setFrom(files(["${project.buildDir}/jacoco/${testTaskName}.exec"]))
//You need to make sure this evaluates after the task begins, not at the gradle configuration stage
doFirst {
//Now look for any files matching *.ec - You can add more details about specific flavor directories if needed.
def instrumentationTestCoverageDirs = project.fileTree("${project.buildDir}/outputs/code_coverage")
.matching { include "**/*.ec" }
//Take this file set and combine it with the UnitTest file set
def allCodeCoverageFiles = instrumentationTestCoverageDirs.files + executionData.files
//If you want to log out what files you are including, use this (if it gives warnings on the info lines, you can simply change them to `println`
project.logger.with {
info("using following code coverage files for ${taskName}")
allCodeCoverageFiles.each { coverageFile ->
info(coverageFile.path)
}
}
executionData.setFrom(allCodeCoverageFiles)
}
为了为单元和 Ui 测试生成代码覆盖率,我已经实现了这个 jacoco.gradle
script
apply plugin: 'jacoco'
jacoco {
toolVersion = "0.8.5"
}
tasks.withType(Test) {
jacoco.includeNoLocationClasses = true
}
project.afterEvaluate {
android.applicationVariants.all { variant ->
def variantName = variant.name
def testTaskName = "test${variantName.capitalize()}UnitTest"
def uiTestCoverageTaskName = "create${variantName.capitalize()}CoverageReport"
tasks.create(
name: "${testTaskName}Coverage",
type: JacocoReport,
dependsOn: ["$testTaskName", "$uiTestCoverageTaskName"]) {
group = "Reporting"
description = "Generate Jacoco coverage reports for the ${variantName.capitalize()} build."
reports {
html.enabled = true
xml.enabled = true
}
def excludes = [
'**/R.class',
'**/R$*.class',
'**/BuildConfig.*',
'**/Manifest*.*',
'**/*Test*.*',
'android/**/*.*',
'**/*Application*.*',
'**/*Dagger*.*',
'**/*Hilt*.*',
'**/*GeneratedInjectorModuleDeps*.*'
]
def javaClasses = fileTree(dir: variant.javaCompiler.destinationDir, excludes: excludes)
def kotlinClasses = fileTree(dir: "${buildDir}/tmp/kotlin-classes/${variantName}", excludes: excludes)
classDirectories.setFrom(files([javaClasses, kotlinClasses]))
sourceDirectories.setFrom(
files([
"$project.projectDir/src/main/java",
"$project.projectDir/src/${variantName}/java",
"$project.projectDir/src/main/kotlin",
"$project.projectDir/src/${variantName}/kotlin"
]))
executionData.setFrom(
files([
"${project.buildDir}/jacoco/${testTaskName}.exec",
"${project.buildDir}/outputs/code_coverage/${variantName}AndroidTest/connected/*coverage.ec"
])
)
}
}
}
我在我的 app.build 中应用了这个脚本,就像这样 apply from: 'buildscripts/jacoco.gradle'
此任务可以生成一个单元和 ui 特定风格的测试覆盖率。
但是,当我使用 ./gradlew testDebugUnitTestCoverage
启动 gradle 任务时,测试执行正常,但在收集 UI 测试覆盖率时,我收到此错误:
Unable to read execution data file /.../app/build/outputs/code_coverage/debugAndroidTest/connected/*coverage.ec
我的项目层次结构如下所示
我正在使用 Gradle 6.1.1 和 Android Gradle Build 工具 4.0.0
在以前的版本中,文件名只是 coverage.ec
,因此通配符查找可以毫无问题地找到该文件。还有一些设备提供的模型不包含空格,这些也很好。
您 运行 的原因是 name/model 设备名称中包含空格。 “*coverage.ec”的通配符查找无法正确解析包含空格的文件名。
仍然可以抓取文件,只是需要多做一些工作。 换出:
executionData.setFrom(
files([
"${project.buildDir}/jacoco/${testTaskName}.exec",
"${project.buildDir}/outputs/code_coverage/${variantName}AndroidTest/connected/*coverage.ec"
])
)
//Set your UnitTest .exec file
executionData.setFrom(files(["${project.buildDir}/jacoco/${testTaskName}.exec"]))
//You need to make sure this evaluates after the task begins, not at the gradle configuration stage
doFirst {
//Now look for any files matching *.ec - You can add more details about specific flavor directories if needed.
def instrumentationTestCoverageDirs = project.fileTree("${project.buildDir}/outputs/code_coverage")
.matching { include "**/*.ec" }
//Take this file set and combine it with the UnitTest file set
def allCodeCoverageFiles = instrumentationTestCoverageDirs.files + executionData.files
//If you want to log out what files you are including, use this (if it gives warnings on the info lines, you can simply change them to `println`
project.logger.with {
info("using following code coverage files for ${taskName}")
allCodeCoverageFiles.each { coverageFile ->
info(coverageFile.path)
}
}
executionData.setFrom(allCodeCoverageFiles)
}