Jacoco offline instrumentation Gradle script
Asked Answered
T

4

13

I tried looking for Jacoco offline instrumentation gradle script snippets but couldn't find one. Is it possible to do Jacoco offline instrumentation through gradle scripts ? If yes...An example of it would be greats. Thanks.

Toulouse answered 28/12, 2016 at 22:48 Comment(2)
IMHO there is no good reason to do the offline byte-code instrumentation anymore. Using a Java agent (like JaCoCo) is the most straightforward way.Sommerville
@G.Demecki I would usually agree, but there are Java toolchains out there that do not fully support on-the-fly instrumentation through Java agents (one example is the real-time capable JamaicaVM by Aicas).Overspend
B
12

Here is an example of Gradle script that performs offline instrumentation using JaCoCo Ant Task:

apply plugin: 'java'

configurations {
  jacoco
  jacocoRuntime
}

dependencies {
  jacoco group: 'org.jacoco', name: 'org.jacoco.ant', version: '0.7.9', classifier: 'nodeps'
  jacocoRuntime group: 'org.jacoco', name: 'org.jacoco.agent', version: '0.7.9', classifier: 'runtime'
  testCompile 'junit:junit:4.12'
}

repositories {
  mavenCentral()
}

task instrument(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.output.classesDir)
    }
  }
}

gradle.taskGraph.whenReady { graph ->
  if (graph.hasTask(instrument)) {
    tasks.withType(Test) {
      doFirst {
        systemProperty 'jacoco-agent.destfile', buildDir.path + '/jacoco/tests.exec'
        classpath = files(instrument.outputDir) + classpath + configurations.jacocoRuntime
      }
    }
  }
}

task report(dependsOn: ['instrument', 'test']) {
  doLast {
    ant.taskdef(name: 'report',
                classname: 'org.jacoco.ant.ReportTask',
                classpath: configurations.jacoco.asPath)
    ant.report() {
      executiondata {
        ant.file(file: buildDir.path + '/jacoco/tests.exec')
      }
      structure(name: 'Example') {
         classfiles {
           fileset(dir: sourceSets.main.output.classesDir)
         }
         sourcefiles {
           fileset(dir: 'src/main/java')
         }
      }
      html(destdir: buildDir.path + '/reports/jacoco')
    }
  }
}
Blastosphere answered 15/2, 2017 at 0:56 Comment(6)
Can confirm this works. Any thought about getting this in the official plugin?Kalina
@KyleC, just for the reference: Add offline instrumentation support to Gradle Jacoco plugin · Issue #2429 · gradle/gradle.Republic
Doesn't work in gradle 5.X since sourceSets.main.output.classesDir is not available after gradle 4.X.Biparous
For gradle 5 and above replace fileset(dir: sourceSets.main.output.classesDir) with sourceSets.main.output.classesDirs.each { fileset(dir: it) }. I tested this with gradle 6.0.1 and it workedGradatim
hi @MohammadAlavi Could you please add your complete offline instrument script over here, as its not working for meBurkes
@Burkes Please check out this repo github.com/AureaMohammadAlavi/… it contains a sample project that uses jacoco offline instrumentationGradatim
A
5

classesDir is not available in Gradle 5 this offline instrumentation code worked for me on Gradle 5.1.1

 task instrument(dependsOn: [classes, project.configurations.jacocoAnt]) {

 inputs.files classes.outputs.files
 File outputDir = new File(project.buildDir, 'instrumentedClasses')
 outputs.dir outputDir
 doFirst {
     project.delete(outputDir)
     ant.taskdef(
             resource: 'org/jacoco/ant/antlib.xml',
             classpath: project.configurations.jacocoAnt.asPath,
             uri: 'jacoco'
     )
     def instrumented = false
     if (file(sourceSets.main.java.outputDir).exists()) {
         def instrumentedClassedDir = "${outputDir}/${sourceSets.main.java}"
         ant.'jacoco:instrument'(destdir: instrumentedClassedDir) {
             fileset(dir: sourceSets.main.java.outputDir, includes: '**/*.class')
         }
         //Replace the classes dir in the test classpath with the instrumented one
         sourceSets.test.runtimeClasspath -= files(sourceSets.main.java.outputDir)
         sourceSets.test.runtimeClasspath += files(instrumentedClassedDir)
         instrumented = true
     }
     if (instrumented) {
         test.jvmArgs += '-noverify'
     }
 }
}


test.dependsOn instrument

The above code is taken from the link https://github.com/esdk/g30l0/commit/82af4c9aad50aadc40d940471fe1b934473170c7 pease follow for more information.

Americanism answered 26/11, 2019 at 8:49 Comment(1)
Works for me. Thanks a lot!Molder
M
1

The answer https://mcmap.net/q/868553/-jacoco-offline-instrumentation-gradle-script works for me(with some adapting to a newer gradle version).

If you have multi-module gradle project, then you should add some extra configuration to support cross-module code coverage.

For more details see Cross-module code coverage with Jacoco offline instrumentation in gradle mutlimodule project

Also, there is a working example: https://github.com/SurpSG/jacoco-offline-instrumentation

UPD: there is alternative jacoco gradle plugin that uses jacoco in offline mode

Molder answered 10/2, 2020 at 19:22 Comment(0)
A
-1

The gradle jacoco plugin doesn't support offline instrumentation, it always does online instrumentation via the java agent.

If the ant jacoco plugin supports offline instrumentation that's likely the best way to get offline instrumentation working in gradle

Antipas answered 29/12, 2016 at 0:48 Comment(4)
could you point the script/snippet from doc where he is doing offline instrumentation....I couldn't figure out the script that does offline instrumentation. I didn't get where he is doing that in examples. If you could through the snippets that would be great.Toulouse
Instrumentation with a Java agent - is on-the-fly instrumentation. Offline instrumentation doesn't require java agent. And I doubt that Gradle plugin supports this, and that's probably why you @Toulouse can't find examples.Blastosphere
@LanceJava I guess you can edit an answer to get rid of this confusion ;)Blastosphere
Jacoco supports offline instrumentation : jacoco.org/jacoco/trunk/doc/offline.html , but the gradle plugin doesn't leverage it, i.e. you can't have a Gradle task which will instrument classes, unless you wrap the Ant library altogether.Toggle

© 2022 - 2024 — McMap. All rights reserved.