Is it possible for Instrumented tests to create coverage for a library module?

被刻印的时光 ゝ 提交于 2021-01-27 21:05:51

问题


I am in the process of modularising the app I am working on and my coverage has dropped over 20% since splitting my instrumentation tests into the app module.

The app is being split into app, core, custom, where core is an android library and the other 2 modules are apps. The majority of the app's functionality will live in core and it is currently mostly tested through instrumentation tests which now reside in app.

Is there a way that instrumentation tests in an application module can generate a coverage report that will include library module sources?

I looked at this question here which bears great similarity to my dilemma but this seems outdated as publishNonDefault is deprecated and does nothing as libraries now publish all variants

My efforts are ongoing on this PR

It will be difficult to complete modularisation with such a drop of coverage, I would expect the coverage to be unchanged post modularisation.

EDIT: I have created a repro project here


回答1:


Eventual answer came from here so all credit to them. Posting the contents of the file here for anybody looking in the future

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 probably needs some improvement for a modern Android application eg Dagger/ViewBinding.

I applied this in my app/build.gradle and after running gradlew jacocoTestReport the report with full coverage was present in [projRoot]/build/coverage-report.

Repro project has been updated with the solution.




回答2:


See the JacocoMerge task which can merge multiple jacoco execution files into a single file. You can then generate a JacocoReport from the merged exec file




回答3:


No.

Just add your instrumentation tests to the module that has the code under test.

Was under a misconception that instrumentation tests could not be run on a library project due to this SO answer, I have proposed an edit to reflect the up to date documentation.

EDIT: I later found a solution but honestly it probably should not be used and this is the path you should go down. Instrumentation tests probably shouldn't be used for coverage to begin with and unless you are stuck with legacy do not use the solution presented on this page.




回答4:


See the JaCoCo plugin docs which show that a task named "jacocoTestReport" is added by the JaCoCo plugin. And you can see there's an "additionalSourceDirs" property on the JacocoReport task

So you can do something like

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
} 


来源:https://stackoverflow.com/questions/58415184/is-it-possible-for-instrumented-tests-to-create-coverage-for-a-library-module

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!