【问题标题】:Is it possible for Instrumented tests to create coverage for a library module?Instrumented 测试是否可以为库模块创建覆盖范围?
【发布时间】:2019-10-16 14:00:41
【问题描述】:

我正在对我正在开发的应用程序进行模块化处理,自从将仪器测试拆分到应用程序模块中后,我的覆盖率下降了 20% 以上。

应用程序被拆分为appcorecustom,其中core 是一个 android 库,其他 2 个模块是应用程序。该应用程序的大部分功能将位于 core 中,目前主要通过仪器测试进行测试,现在位于 app 中。

有没有一种方法可以让应用程序模块中的插桩测试生成包含库模块源的覆盖率报告?

我查看了这个问题 here,它与我的困境非常相似,但这似乎已经过时,因为 publishNonDefault 已被弃用,并且没有任何作用,因为图书馆现在发布了所有变体

我的努力仍在this PR

在覆盖率下降的情况下很难完成模块化,我希望覆盖率在模块化后保持不变。

编辑:我创建了一个复制项目here

【问题讨论】:

    标签: android gradle jacoco multi-module


    【解决方案1】:

    最终的答案来自here,所以一切都归功于他们。将文件的内容发布在这里,以供将来寻找的任何人使用

    apply plugin: 'jacoco'
    
    jacoco {
        toolVersion = "$jacocoVersion"
    }
    
    tasks.withType(Test) {
        jacoco.includeNoLocationClasses = true
    }
    
    task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest', 'createDebugCoverageReport']) {
    
        group "Reporting"
        description "Generate Jacoco coverage reports."
    
        reports {
            xml.enabled = true
            html.enabled = true
            html.destination file("${rootProject.buildDir}/coverage-report")
        }
    
        def javaClasses = []
        def kotlinClasses = []
        def javaSrc = []
        def kotlinSrc = []
        def execution = []
    
        def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*']
    
        rootProject.subprojects.each { proj ->
            javaClasses   << fileTree(dir: "$proj.buildDir/intermediates/javac/debug", excludes: fileFilter)
            kotlinClasses << fileTree(dir: "$proj.buildDir/tmp/kotlin-classes/debug", excludes: fileFilter)
            javaSrc       << "$proj.projectDir/src/main/java"
            kotlinSrc     << "$proj.projectDir/src/main/kotlin"
            execution     << fileTree(dir: proj.buildDir,
                    includes: ['jacoco/testDebugUnitTest.exec',
                               'outputs/code_coverage/debugAndroidTest/connected/**/*.ec'])
        }
    
        sourceDirectories = files([javaSrc, kotlinSrc])
        classDirectories = files([javaClasses, kotlinClasses])
    
        print execution
    
        executionData = files(execution)
    
        doLast() {
            print "file://${reports.html.destination}/index.html"
        }
    }
    

    FileFilter 可能需要对现代 Android 应用程序进行一些改进,例如 Dagger/ViewBinding。

    我在app/build.gradle 中应用了此功能,在运行gradlew jacocoTestReport 后,[projRoot]/build/coverage-report 中出现了完整覆盖的报告。

    Repro 项目已更新解决方案。

    【讨论】:

    • 生成报告的index.html 文件头是上次扫描的模块名称,而不是在正常覆盖率报告中显示的debugAndroidTest。我们可以将报告标题更改为debugAndroidTest 吗?
    【解决方案2】:

    参见JacocoMerge 任务,它可以将多个 jacoco 执行文件合并到一个文件中。然后您可以从合并的 exec 文件中生成 JacocoReport

    【讨论】:

    • 不幸的是,我认为这不是解决方案。我不想要合并报告(codecov 为我处理)。我想在我的app 模块中报告我的core 模块中的引用代码。
    • 您可以使用JacocoReport.additionalSourceDirs(...)添加额外的来源
    • 我必须编写自己的任务并在其中指定它吗?对不起,但我不知道这应该去哪里,在 jacoco 插件扩展中我只看到 toolsVersion & reportsDir
    • 不,请参阅我的其他答案。您将配置 JaCoCo 插件添加的任务之一
    • jacocoTestReport 如果我没记错的话,是用于单元测试吗?我认为这与createDebugCoverageReport 运行的仪器覆盖率报告无关?我将在我的示例项目中尝试一下
    【解决方案3】:

    没有。

    只需将您的仪器测试添加到包含被测代码的模块即可。

    由于这个SO answer,我误以为仪器测试无法在库项目上运行,我建议进行编辑以反映最新的文档。

    编辑:我后来找到了一个解决方案,但老实说它可能不应该被使用,这是你应该走的路。仪表测试可能不应该用于覆盖范围,除非您被遗留问题困扰,否则不要使用此页面上提供的解决方案。

    【讨论】:

      【解决方案4】:

      查看JaCoCo plugin docs,它表明 JaCoCo 插件添加了名为“jacocoTestReport”的任务。你可以看到JacocoReport任务上有一个“additionalSourceDirs”属性

      所以你可以做类似的事情

      apply plugin: 'java-library' 
      apply plugin: 'jacoco' 
      evaluationDependsOn ':another-project'
      tasks.withType(JacocoReport) {
         def otherSourceSet = project(':another-project').sourceSets.main
         additionalSourceDirs.from otherSourceSet.allJava
         additionalClassDirs.from otherSourceSet.output
      } 
      

      【讨论】:

      • 非常类似于您的回答here。似乎 jacocoReport 任务的自定义配置比这里看到的要复杂一些。 This article 更详细,但我认为已经过时了,因为 .class 文件的位置与描述不符
      • 查看我的更新以使用 tasks.withType{...} 和配置 additionalClassDirs
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-02
      • 2014-01-29
      • 1970-01-01
      • 1970-01-01
      • 2021-09-17
      • 1970-01-01
      • 2022-06-12
      相关资源
      最近更新 更多