Gradle Jacoco - coverage reports includes classes excluded in configuration - gradle

I added to a project a set of sources that don't have tests and I don't want them spoil my test coverage statistics. I configured Jacoco in the next way :
test {
jacoco{
excludes = ['org/bla/**']
includes = ['com/bla/**']
append = false
}
}
jacocoTestReport {
dependsOn test
description = "Generate Jacoco coverage reports after running tests."
reports {
xml.enabled true
html.enabled true
}
classDirectories = fileTree(dir: 'build/classes/main', include: 'com/bla/**')
sourceDirectories = fileTree(dir: 'scr/main/java', include: 'com/bla/**')
}
But anyway, when generating the report, Jacoco also includes classes from org.bla
Can someone help me ?
EDIT
After some debugging, it appears that all default outputs are added to org.gradle.testing.jacoco.tasks.JacocoReport#classDirectories in a private method org.gradle.testing.jacoco.plugins.JacocoPlugin#addDefaultReportTasks
That's visible when using such code :
jacocoTestReport {
classDirectories = files('build/classes/main/com/bla')
println("-----------------------------------------------------------")
getAllClassDirs().each { File file ->
println(file.absolutePath)
}
println("-----------------------------------------------------------")
getAdditionalClassDirs().each{ File file ->
println(file.absolutePath)
}
}
jacocoTestReport << {
println("-----------------------------------------------------------")
getAllClassDirs().each { File file ->
println(file.absolutePath)
}
println("-----------------------------------------------------------")
getAdditionalClassDirs().each{ File file ->
println(file.absolutePath)
}
}
Output
-----------------------------------------------------------
<path_here>\build\classes\main\com\bla
-----------------------------------------------------------
....more text here
-----------------------------------------------------------
<path_here>\build\classes\main\com\bla
<path_here>\build\classes\main
<path_here>\build\resources\main
-----------------------------------------------------------
So - the question is : is it possible to override somehow org.gradle.testing.jacoco.plugins.JacocoPlugin#addDefaultReportTasks method, or override completely org.gradle.testing.jacoco.plugins.JacocoPlugin class ?

Ok, found a workaround :
jacocoTestReport.doFirst{
classDirectories = files('build/classes/main/com/bla')
}
This overrides classDirectories set by JacocoPlugin class.

If you have a task names something other than
test
that runs unit tests, you should be able to generate the report adding the following task to your build.gradle file:
jacocoTestReport {
group = "Reporting"
description = "Generates Jacoco coverage reports for unit tests"
executionData = files('build/jacoco/unitTest.exec')
reports {
html.destination = 'build/reports/coverage'
}
}
This needs to be called explicitly after the task to run unit tests, e.g:
gradle unitTest jacocoTestReport

Related

jacocoTestReport always SKIPPED

Expected Behavior
jacocoTestReport work
Current Behavior
jacocoTestReport SKIPPED
Context
I created a task whose type is Test, and jacocoTestReport depends on the task. When I ran the task, jacocoTestReport did not work and I got the following information
jacocoTestReport SKIPPED
I find if I use the task test directly, jacocoTestReport worked fine. It makes me confused
the following code caused the above issue
plugins {
id 'java'
id 'jacoco'
}
repositories {
mavenCentral()
}
dependencies {
}
task myTest(type: Test) {
useTestNG()
useJUnitPlatform()
finalizedBy jacocoTestReport
reports {
junitXml.required = false
html.required = true
}
jacoco {
enabled = true
destinationFile = layout.buildDirectory.file("jacoco/${name}.exec").get().asFile
}
}
jacocoTestReport {
// tests are required to run before generating the report
dependsOn myTest
reports {
xml.required = false
csv.required = false
html.outputLocation = layout.buildDirectory.dir('jacocoHtml')
}
}
Steps to Reproduce
example project
Your Environment
Gradle 7.1.1
It is expected, not an issue. just because I use the jacocoTestReport in a wrong way
see https://github.com/gradle/gradle/issues/18271

jacocoTest exclusion has no effect

I have a gradle project and I want to exclude some directories from TC coverage. This is what I am giving in the task
jacocoTestReport {
reports {
xml.enabled true
csv.enabled false
html.enabled true
}
afterEvaluate {
classDirectories.setFrom(files(classDirectories.files.collect {
fileTree(dir: it).exclude(
// define here
'com/this/that'
)
}))
}
}
However the classes still shows up in the coverage.
What am I missing?
afterEvaluate runs in Gradle's configuration phase which is before any tasks have executed and before any classes have been compiled (see build phases)
I'm guessing you want something like
test {
jacoco {
excludes = ['com/this/that/*']
}
}

jacocoRootReport only shows coverage from last project of multi-project gradle build

I'm upgrading my Gradle 4 multi-project setup to Gradle 6. I've followed instructions here:
https://stackoverflow.com/a/56181389
and I've bumped the jacoco version to 0.8.5. Right now the only problem is that the human-readable coverage report seems to be missing most of the coverage data that it was showing under the old version. It seems that the coverage report is only reflecting the last (most recently tested) project. It used to work fine under Gradle 4. I'm using Java 8.
I ran the gradle build using --debug, and I notice that the test.exec file is deleted repeatedly, once for each subproject that has tests. I think this is the problem, but I don't know how to prevent deletion of this file.
2020-04-16T09:16:21.048-0600 [DEBUG] [org.gradle.internal.file.impl.DefaultDeleter] Deleting /Users/bishop/dev/aep/edge-profile-lookup-target/build/jacoco/test.exec
Can someone please help me fix this so that all of the coverage (from each of the tests which ran against each of the sub projects) appear in a single coverage report?
Here are the parts of the main build.gradle file that seem relevant:
buildscript {
ext {
jacocoVersion = '0.8.5'
...
}
...
}
allprojects {
...
apply plugin: 'jacoco'
...
}
subprojects {
tasks.withType(Test) {
// redirect all coverage data to one file
jacoco {
destinationFile = file("$rootProject.buildDir/jacoco/test.exec")
}
}
jacoco {
toolVersion = jacocoVersion
}
jacocoTestReport {
additionalSourceDirs.from = files(sourceSets.main.allSource.srcDirs)
sourceDirectories.from = files(sourceSets.main.allSource.srcDirs)
classDirectories.from = files(sourceSets.main.output.collect {
fileTree(dir: it, exclude: project.properties['BUILD_COVERAGE_EXCLUSIONS'].tokenize(','))
})
reports {
html.enabled = true
xml.enabled = true
csv.enabled = false
}
}
}
task jacocoRootReport(type: JacocoReport) {
dependsOn = subprojects.test
additionalSourceDirs.from = files(subprojects.sourceSets.main.allSource.srcDirs)
sourceDirectories.from = files(subprojects.sourceSets.main.allSource.srcDirs)
classDirectories.from = files(subprojects.jacocoTestReport.classDirectories)
executionData.from = files(subprojects.jacocoTestReport.executionData)
reports {
html.enabled = true
xml.enabled = true
csv.enabled = false
}
onlyIf = {
true
}
doFirst {
executionData.from = files(executionData.findAll {
it.exists()
})
}
}
...
apply plugin: 'jacoco'
configurations.create("jacoco")
configurations {
jacoco
}
dependencies {
jacocoAnt group: 'org.jacoco', name: 'org.jacoco.ant', version: jacocoVersion
jacocoAnt group: 'org.ow2.asm', name: 'asm', version: asmVersion
}
task copyRuntimeLibs(type: Copy) {
from configurations.jacoco
into "$rootProject.buildDir/libs"
}
build.dependsOn copyRuntimeLibs
The following:
jacoco {
destinationFile = file("$rootProject.buildDir/jacoco/test.exec")
}
configures Jacoco to always use the same output file.
So the issue is most likely that more recent Gradle versions work on separating colliding outputs.
I would recommend looking at the recently published sample on how to setup Jacoco in a multi project instead of attempting to rely on colliding outputs.

How to get Jacoco reports for the Karate test feature files using gradle

How to get Jacoco reports for the Karate test feature files using Gradle.
My project is a Gradle project and I am trying to integrate jacoco report feature in my project for the karate tests. The server is running in my local on 8080 port.
I am doing the following way to generate jacoco report and please let me know is my approach correct and also give me a solution to get the jacoco report for the gradle project.
1) First I am trying to generate jacoco execution data with the help of jacocoagent.jar as follows with a Gradle task:
java -javaagent:/pathtojacocojar/jacocoagent.jar=destfile=/pathtojocofile/jacoco.exec -jar my-app.jar
2) Next, I am running a Gradle task to generate the report
project.task ('jacocoAPIReport',type: org.gradle.testing.jacoco.tasks.JacocoReport) {
additionalSourceDirs = files(project.sourceSets.main.allSource.srcDirs)
sourceDirectories = files(project.sourceSets.main.allSource.srcDirs)
classDirectories = files(project.sourceSets.main.output)
executionData = fileTree(dir: project.projectDir, includes: ["**/*.exec", "**/*.ec"])
reports {
html.enabled = true
xml.enabled = true
csv.enabled = false
}
onlyIf = {
true
}
doFirst {
executionData = files(executionData.findAll {
it.exists()
})
}
}
project.task('apiTest', type: Test) {
description = 'Runs the api tests'
group = 'verification'
testClassesDirs = project.sourceSets.apiTest.output.classesDirs
classpath =
project.sourceSets.apiTest.runtimeClasspath
useJUnitPlatform()
outputs.upToDateWhen { false }
finalizedBy jacocoAPIReport
}
I don't see any of my application's classes in the jococo.exec file. I think, bcz of that I am always getting the coverage report as 0%.
The server is running in my local on 8080 port.
I don't think that is going to work. Depending on how your code is structured you need to instrument the code of the server.
I suggest trying to get a simple unit test of a Java method to work with Gradle. If that works, then use the same approach for the server-side code and it will work.

Gradle, Kotlin, Junit5 and Jacoco - 0% coverage reported

We would like to use Gradle in conjunction with Kotlin and Jacoco (+JUnit 5) for generating a code coverage report.
Our project directory tree looks as follows:
project/{src,test}/main/kotlin ...
Our build.gradle file looks as follows:
jacoco {
toolVersion = "0.7.9"
reportsDir = file("$buildDir/reports")
applyTo junitPlatformTest
}
jacocoTestReport {
group = "Reporting"
description = "Generate Jacoco coverage report."
classDirectories = fileTree(
dir: "$buildDir/classes/kotlin/main"
)
def coverageSourceDirs = [
"src/main/kotlin"
]
additionalSourceDirs = files(coverageSourceDirs)
sourceDirectories = files(coverageSourceDirs)
executionData = files("$buildDir/jacoco/junitPlatformTest.exec")
reports {
xml.enabled = true
html.enabled = true
csv.enabled = true
}
}
test {
jacoco {
append = false
destinationFile = file("$buildDir/jacoco/junitPlatformTest.exec")
includeNoLocationClasses = true
}
}
test.dependsOn junitPlatformTest
With this configuration, Jacoco generates a html report and puts it under build/reports/test/html. However, it shows me 0% coverage. This should not be the case, because I have one test case that excercices all methods for a single dummy class in the project.
I went through several posts such as:
http://vgaidarji.me/blog/2017/12/20/how-to-configure-jacoco-for-kotlin-and-java-project/
Jacoco is reporting 0 coverage of Kotlin classes by unit tests, in an Android project
JaCoCo returning 0% Coverage with Kotlin and Android 3.0
However, I could not quite find a solution that worked for me, yet.
I recently hit this issue when upgrading form junit 4 -> 5. In my case I had to re-arrange the declaration of the dependencies as outlined here. If you change to this format you should see the coverage reported correctly again without having to change any other configuration.
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
}

Resources