How to configure gradle to produce code coverage for sonar when i'm using powermock in my tests? I found that jacoco don't support that. Is there any other codecoverage plugin to work with powermock?
3 Answers
Jacoco Offline Instrumentation is the solution for this.
see my gradle build file
Build and run tests:
Linux:
\$ ./gradlew
Windows:
\$ gradlew
------------------------------------------
"""
apply plugin: 'java'
apply plugin: 'org.sonarqube'
apply plugin: 'jacoco'
// Project group and version
group 'com.abcd.jacocoTest'
version '1.0.0'
// JDK version source compatibility
sourceCompatibility = 1.8
// JDK version target compatibility
targetCompatibility = 1.8
configurations {
jacocoAnt
jacocoRuntime
}
task wrapper(type: Wrapper) {
gradleVersion = "4.5.1"
}
defaultTasks 'clean', 'test'
buildscript {
repositories {
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.6.2"
}
}
repositories {
mavenCentral()
}
dependencies {
jacocoAnt group: 'org.jacoco', name: 'org.jacoco.ant', version: '0.8.1'
jacocoAgent group: 'org.jacoco', name: 'org.jacoco.agent', version: '0.8.1'
testCompile group: 'junit', name: 'junit', version: '4.12'
testCompile group: 'org.mockito', name: 'mockito-core', version: '2.8.9'
testCompile group: 'org.powermock', name: 'powermock-module-junit4', version: '1.7.4'
testCompile group: 'org.powermock', name: 'powermock-api-mockito2', version: '1.7.4'
testCompile group: 'org.powermock', name: 'powermock-api-easymock', version: '1.7.4'
}
test {
testLogging {
afterSuite { desc, result ->
if (!desc.parent) { // will match the outermost suite
println "Unit Tests: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)"
}
}
}
jacoco {
append = "false"
destinationFile = file("$buildDir/reports/jacoco/jacoco-sonar/jacoco-coverage.exec")
}
}
jacoco {
toolVersion = "0.8.0"
}
jacocoTestReport {
reports {
html.destination file("${buildDir}/reports/jacoco/jacocoHtml")
}
}
sonarqube {
properties {
property "sonar.projectName", 'JacocoTest'
property "sonar.host.url", "http://localhost:9000"
property "sonar.java.binaries", "${buildDir}/classes"
property "sonar.java.libraries", "**/*.jar"
property "sonar.dynamicAnalysis", "reuseReports"
property "sonar.jacoco.reportPaths", "${buildDir}/reports/jacoco/jacoco-sonar/jacoco-coverage.exec"
}
}
task instrument(dependsOn: ['classes']) {
ext.outputDir = buildDir.path + '/reports/classes-instrumented'
doLast {
ant.taskdef(name: 'instrument',
classname: 'org.jacoco.ant.InstrumentTask',
classpath: configurations.jacocoAnt.asPath)
ant.instrument(destdir: outputDir) {
fileset(dir: sourceSets.main.output.classesDir)
}
}
}
gradle.taskGraph.whenReady { graph ->
if (graph.hasTask(instrument)) {
tasks.withType(Test) {
doFirst {
classpath = files(instrument.outputDir) + classpath + configurations.jacocoRuntime
}
}
}
}
task report(dependsOn: ['instrument', 'test']) {
doLast {
ant.taskdef(name: 'report',
classname: 'org.jacoco.ant.ReportTask',
classpath: configurations.jacocoAnt.asPath)
ant.report() {
executiondata {
ant.file(file: buildDir.path + '/reports/jacoco/jacoco-sonar/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')
}
}
}
Here report task will create the offline instrumentation files of the project.
Finally, execute sonarqube task. Then you can see the coverage of the powermocked classes also has included.
Execution command ./gradlew report sonarqube
Then go and see in your sonarqube host (localhost:9000).

- 141
- 1
- 10
You could try to use JaCoCo offline instrumentation instead of on-the-fly instrumentation as documented at https://github.com/powermock/powermock/wiki/Code-coverage-with-JaCoCo as long as https://github.com/powermock/powermock/issues/727 is not fixed which would make PowerMock compatible with JaCoCo on-the-fly instrumentation.
Alternatively you could use a different mocking framework, like e. g. JMockit. This is compatible with JaCoCo on-the-fly instrumentation as far as I remember.

- 35,631
- 4
- 76
- 102
-
I looked at JMockit but it is a very simple mock framework. I need to mock object creation in tested class. It's hard with JMock. Even mocking conrete class is hard. From infomations which i found JMock can mock interfaces. So in my tests i need to create new interface and wrap my class. It's too much code to change to run tests only. I'm checking JaCoCo with offline instrumentation but cant find example in gradle. – skoczo Sep 01 '17 at 07:34
-
Don't confuse jMock with JMockit. JMockit is probably the most powerful mocking framework you can find and up to now I didn't stumble upon something that was not possible with JMockit. – Vampire Sep 01 '17 at 07:42
-
Sorry for mixing framework names. Of course i mean JMockit. Bit still, JMockit is unintuitive for me. I don't want to write extra interfaces ony for testing. Not always everything, which i wat to mock, is properly designed and has interface. – skoczo Sep 01 '17 at 12:14
-
You don't need to. JMockit can easily mock interfaces, classes, static methods, final methods, hell, even static initializer blocks, constructors and private methods can be mocked without any hassle. You don't even need to create a mock and inject it manually into the tested classes like many mock frameworks require, but it "just works". I assume you still confuse jMock for JMockit. JMockit also has a great tutorial on the web page that explains almost anything and a very responsive and helping developer. – Vampire Sep 01 '17 at 14:06
I resigned to use gradle and jacoco. Now i'm using maven + cobertura + powermock and everything works without hacks. Why i'm using maven? Because i can't find how to produce xml code coverage report in cobertura using gradle.

- 75
- 1
- 12
-
Asking here does not void the need to Google. A simple search revealed as first hit https://stackoverflow.com/questions/41370815/jacoco-offline-instrumentation-gradle-script where Jacoco offline instrumentation with Gradle is shown. And at https://github.com/stevesaliman/gradle-cobertura-plugin you find a Gradle plugin that integrates Cobertura. – Vampire Sep 01 '17 at 14:10
-
I found that before asking here, but this solution not produce coverage in xml format. – skoczo Sep 05 '17 at 07:01
-
-
1Assuming you meant Cobertura, it would have helped to have a 5 seconds look at the Usage page and searching for `XML`, that would have revealed `coverageFormats = [
]: Tells the plugin what report formats should be used. Cobertura supports 'html' and 'xml'. The default is html.` – Vampire Sep 05 '17 at 09:46 -