【问题标题】:Jacoco can't read .ec fileJacoco 无法读取 .ec 文件
【发布时间】:2020-10-23 11:09:15
【问题描述】:

为了生成单元和 Ui 测试的代码覆盖率,我实现了这个jacoco.gradlescript

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 Tools 4.0.0

【问题讨论】:

  • 这个问题你解决了吗?
  • @dudi testInstrumentationRunnerArguments clearPackageData: 'true' 是否存在于您的 gradle 文件中?

标签: android unit-testing gradle code-coverage jacoco


【解决方案1】:

在以前的版本中,文件的名称只是coverage.ec,因此通配符查找找到该文件没有问题。并且有许多设备提供了不包含空格的模型,这些也很好。

您遇到的问题是由名称中包含空格的设备名称/型号引起的。 “*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)
    }

【讨论】:

  • 非常感谢@Jim Roobbins 为我提供了这个解决方案。我会尽快尝试一下。
  • @JimRobbins,这个解决方案奏效了。谢谢:)
猜你喜欢
  • 2015-04-07
  • 1970-01-01
  • 2014-09-17
  • 2014-09-21
  • 2019-05-15
  • 1970-01-01
  • 2012-03-07
  • 2016-06-17
  • 2016-10-19
相关资源
最近更新 更多