问题
I have to use Jacoco offline instrumentation in my project because there is PowerMock that is used as well.
The issue description: suppose you have gradle project with two modules: A, B. Module A
has tests that cover a code from the module B
. On code coverage data collection I figured out that coverage data(should be provided by the module A
) for the module B
is completely missed.
I've created a test project that demonstrates the issue: https://github.com/SurpSG/jacoco-offline-instrumentation
Jacoco offline instrumentation setup for gradle project is based on the answer https://stackoverflow.com/a/42238982/2689114
On the other hand, when I'm using jacoco gradle plugin I can observe that coverage data provided by module A
for module B
successfully collected to a summary report. I've created one more test project to demonstrate this: https://github.com/SurpSG/jacoco-gradle-plugin-merge-coverage
Am I have a wrong setup for the gradle multimodule project + jacoco offline instrumentation?
回答1:
After some investigation, I figured out that modules dependencies in Gradle are resolved via .jar files:
<dependent-module>.classpath contains <dependency-module>.jar
So, in my case, I need to build some special jar that contains instrumented classes.
Instrumenting classes
task preprocessClassesForJacoco(dependsOn: ['classes']) {
ext.outputDir = buildDir.path + '/classes-instrumented'
doLast {
ant.taskdef(name: 'instrument',
classname: 'org.jacoco.ant.InstrumentTask',
classpath: configurations.jacoco.asPath)
ant.instrument(destdir: outputDir) {
fileset(dir: sourceSets.main.java.outputDir, includes: '**/*.class', erroronmissingdir: false)
}
}
}
The next step will be building instrumented jar:
task jacocoInstrumentedJar(type: Jar, dependsOn: [preprocessClassesForJacoco]) {
baseName "${project.name}-instrumented"
from preprocessClassesForJacoco.outputDir // path to instrumented classes
}
And finally, we need to replace the usual .jar with instrumented one
gradle.taskGraph.whenReady { graph ->
if (graph.hasTask(preprocessClassesForJacoco)) {
tasks.withType(Test) {
doFirst {
...
// getting a module dependencies
def modulesDependencies = moduleDependencies(project)
// removing regular jars
classpath -= files(modulesDependencies.jar.outputs.files)
// adding instrumented jars
classpath += files(modulesDependencies.jacocoInstrumentedJar.outputs.files)
}
}
}
}
I've updated the example project https://github.com/SurpSG/jacoco-offline-instrumentation with steps described above. Feel free to check out the project to try.
来源:https://stackoverflow.com/questions/60009231/cross-module-code-coverage-with-jacoco-offline-instrumentation-in-gradle-mutlimo