Arbitrate the fight between PowerMock and jacoco with Gradle

Overview

Aiming for 100% java UT coverage with a certain PJ When I created a coverage report with jacoco, test_coverage.png It will be 0% across the board.

Apparently, jacoco doesn't like powermock, a rough man ... That said, powermock addiction is a death.

Workaround

https://github.com/powermock/powermock/wiki/Code-coverage-with-JaCoCo

Second way to get code coverage with JaCoCo - use offline Instrumentation.

Apparently Offline Instrumentation. There is only an implementation example in Maven and there is not much article on how to write in Gradle, so let's write it.

Dependencies

build.gradle


dependencies {
  testCompile group: 'org.mockito', name: 'mockito-core', version: '2.2.7'
  testCompile group: 'org.powermock', name: 'powermock-api-mockito2', version: '2.0.0-beta.5'
  testCompile group: 'org.powermock', name: 'powermock-module-junit4', version: '2.0.0-beta.5'

  jacoco group: 'org.jacoco', name: 'org.jacoco.ant', version: '0.8.2', classifier: 'nodeps'
  jacocoRuntime group: 'org.jacoco', name: 'org.jacoco.agent', version: '0.8.2', classifier: 'runtime'
}

By the way, please note that Offline Instrumentation works after powermock 1.6.6.

Offline Instrumentation

build.gradle


configurations {
  jacoco
  jacocoRuntime
}

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/jacoco-coverage.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/jacoco-coverage.exec')
      }
      structure(name: 'Example') {
         classfiles {
           fileset(dir: sourceSets.main.output.classesDir)
         }
         sourcefiles {
           fileset(dir: 'src/main/java')
         }
      }
      html(destdir: buildDir.path + '/reports/jacoco/test/html')
    }
  }
}

Immediately after compiling, it's an instrument, and it feels like test + jacoco. Now when I try to run the report task,

coverage_after.png

PowerMock and jacoco have been successfully reconciled.

Impressions

I'm not sure what the instrument is still doing. Actually, it is a multi-project configuration, so I would like to combine coverage reports.

So next time, I will try to combine various documents in a multi-project.

Recommended Posts

Arbitrate the fight between PowerMock and jacoco with Gradle
Mock the constructor with PowerMock
[Java] Check the difference between orElse and orElseGet with IntStream
The difference between programming with Ruby classes and programming without it
Understand the difference between each_with_index and each.with_index
Organize the relationship between SLF4J, Logback, and Log4J along with their behavior
About the difference between irb and pry
Download JDK with Gradle and make JRE
[Ruby] Difference between methods with and without self in the class. About class methods and instance methods.
[Java] Understand the difference between List and Set
[iOS] Understand the difference between frame and bounds
[Rails / ActiveRecord] About the difference between create and create!
Build and test Java + Gradle applications with Wercker
Understand the difference between abstract classes and interfaces!
What is the difference between SimpleDateFormat and DateTimeFormatter? ??
Summarize the differences between C # and Java writing
Learn the rudimentary mechanism and usage of Gradle 4.4
Distinguish between integers and decimals with regular expressions
[Swift] About the inability to distinguish between full-width and half-width characters with NS Predicate