问题
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