I'm working on setting up the Jacoco Gradle plugin for my project. The plugin is executing fine and generating the coverage report but it's not excluding packages that I would excluded.
Classes I would like to include are in com/xxx/ws/hn/** and classes I would like excluded are in com/xxx/ws/enterprise/**.
Here's my Gradle script:
apply plugin: "jacoco"
jacoco {
toolVersion = "0.6.2.201302030002"
reportsDir = file("$buildDir/reports/jacoco")
}
test {
jacoco{
excludes = ["com/xx/ws/enterprise/**/*"]
includes = ["com/xxx/ws/hn/**/*"]
append = false
}
}
jacocoTestReport {
dependsOn test
description = "Generate Jacoco coverage reports after running tests."
executionData = files('build/jacoco/test.exec')
reports {
xml.enabled true
html.enabled true
}
}
Am I missing anything here? I've tried various patterns of exclusions including a '.' delimiter for packages instead of a '/' but nothing seems to work. Any help would be greatly appreciated.
I have not verified this but when I read the JaCoCo documentation, it states that wildcards can be used but all examples only have ONE *, not two as your example shows.
http://www.eclemma.org/jacoco/trunk/doc/agent.html
To solidify (and verify) Joachim's answer, I came across this SO post and found that specifying canonical class names, classpath style (with slashes, not periods), with single wildcard characters actually worked well. For example, here is my exclude list that works in my build, as defined as a list in a separate gradle file:
def testExcl = [
'android/*',
'com/android/*',
'com/nativelibs4java/*',
'com/ochafik/*',
'com/fasterxml/*',
'com/esotericsoftware/*',
'com/google/*',
'com/lmax/*',
'com/sun/*',
'jdk/*',
'mockit/*',
'org/apache/*',
'org/bridj/*',
'org/gradle/*',
'org/hamcrest/*',
'org/junit/*',
'org/slf4j/*',
'sun/*',
'worker/*',
'*Test',
'*TestIntegration',
'*AllTests',
'*Suite'
]
I tried probably 10 or 12 other ways of formatting the class names, and this is the only way that actually worked.
I don't know why something like this that is so simple/fundamental is so ungoogleable and difficult to find a definitive answer on in the context of Gradle (i.e. outside JaCoCo's official documentation, where no documentation exists about Gradle integration, but Ant and Maven integration docs are there).
Hopefully this helps if others are flailing trying to get JaCoCo to exclude classes.
UPDATE:
This changed in Gradle 7 (I went from 5.6.1 to 7.1.1, so not sure about Gradle 6) and no longer works.
For Gradle 7 you need to replace / with .; here are my updated exclusions:
def testExcl = [
'android.*',
'com.android.*',
'com.nativelibs4java.*',
'com.ochafik.*',
'com.fasterxml.*',
'com.esotericsoftware.*',
'com.google.*',
'com.lmax.*',
'com.sun.*',
'jdk.*',
'mockit.*',
'org.apache.*',
'org.bridj.*',
'org.gcpud.common.*',
'org.gcpud.testutil.*',
'org.gradle.*',
'org.hamcrest.*',
'org.junit.*',
'org.slf4j.*',
'sun.*',
'worker.*',
'*Test',
'*Test$*',
'*TestIntegration',
'*AllTests',
'*Suite'
]
Also see the following SO post for other means of excluding classes from reporting (exclude from reporting, not coverage itself):
Filter JaCoCo coverage reports with Gradle
Related
I am using the eclipse-pmd plugin, and I am also using PMD via the following Gradle configuration:
plugins {
id 'pmd'
}
pmd {
consoleOutput = true
ruleSets = []
ruleSetFiles = files("pmd-ruleset.xml")
toolVersion = "6.41.0"
}
Both methods are configured to use the same ruleset, and my PATH variable points to PMD 6.41.0 (which I think is what the Eclipse plugin uses), and yet both give different results.
For example, running ./gradlew pmdMain complains about the rule AvoidUncheckedExceptionsInSignatures, but eclipse-pmd does not flag this up at all.
Why might this be?
It turns out that the eclipse-pmd plugin (which I found in C:\Users\{username}\.p2\pool\plugins) comes packaged with its own version of PMD, which in this case is 6.28.0.
This doesn't fully explain the discrepency, since the AvoidUncheckedExceptionsInSignatures rule has been around since PMD 6.13.0, but I'm happy enough to blame the difference in versions for the difference in output.
I am trying to update a gradle 6.x version multi project application to gradle 7.3 as it is the first version to support Java 17. However, I am unable to progress past an issue arising from a task which is not declared in any of my build.gradle files. The error is below: ([] pieces are redacted)
Execution failed for task ':[root module]:[module]:processIntTestResources'.
> Entry [filename] is a duplicate but no duplicate handling strategy has been set. Please refer to https://docs.gradle.org/7.3/dsl/org.gradle.api.tasks.Copy.html#org.gradle.api.tasks.Copy:duplicatesStrategy for details.
I think is associated with a sourceSet for integration tests, however, I never explicitly copy and files for those tests. I have also set all copy instructions to have this configuration with regard to duplicate handling:
duplicatesStrategy = DuplicatesStrategy.INCLUDE
I also tried adding the above to projects which failed because that setting is only valid for Copy type tasks or blocks. I am by no means an expert in gradle and can add any relevant information needed, but I believe I have included what might be most relevant. I am really just looking for a direction I can head in to further debug this issue.
You didn't show much about how you have integration tests configured, but I ran into a similar problem. What saved me was this blog post by Tom Gregory:
Running integration tests in Gradle
Since links can disappear, let me copy and paste the most important part that I found relevant, which is regarding the new (as of Gradle 7.3) JVM Test Suite Plugin that adds support for integration tests. For me, this replaced my old integration test configuration:
testing {
suites {
integrationTest(JvmTestSuite) {
dependencies {
implementation project
}
}
}
}
tasks.named('check') {
dependsOn testing.suites.integrationTest
}
I also found the following useful, which is not in the above blog post, but is a leftover from my previous Gradle 6 configuration. This for me duplicates the 'test' dependencies for 'integrationTest'. This is not the recommended way of handling the test depedencies now (see the JVM Test Suite Plugin documentation), but I still found it useful to get me back running quickly:
configurations {
integrationTestImplementation.extendsFrom testImplementation
integrationTestRuntime.extendsFrom testRuntime
}
I have a multi-module Android project and I'm seeing a discrepancy between the coverage that jacoco reports and what Sonarqube reports.
The project is also a multi-flavor project that generates a lot of different variants. I am using this plugin to help me generate all of the tasks. The tasks generate an individual report for each variant.
When I run my jacoco reports I see this:
When I run the sonar scanner i see this:
I have some exclusions on my project,but even without them the coverage %s don't match.
I feel like I may not be providing the same bytecode as hinted in this question:
Here is my relevant info:
Sonar Version 5.6.
Gradle runner
plugins { id "org.sonarqube" version "2.0.1" }
Sonar config: (on root build.gradle)
sonarqube {
properties {
property "sonar.projectKey", "com.xxx.myApp"
property "sonar.projectName", "Android My App"
property "sonar.projectVersion", "3.0"
property "sonar.java.binaries", "build/classes"
property "sonar.coveragePlugin", "jacoco"
property "sonar.jacoco.reportMissing.force.zero", "false"
}
}
Sonar config (on app/build.gradle)
sonarqube {
properties {
property "sonar.sources", "src/main/java"
property "sonar.tests", "src/test/java"
property "sonar.java.tests", "src/test/java"
property "sonar.junit.reportsPath", "build/test-results/myAppGoogleMobileDebug"
property "sonar.java.binaries", "build/intermediates/classes/myAppGoogleMobile/debug"
property "sonar.jacoco.reportPath", "build/jacoco/testMyAppGoogleMobileDebugUnitTest.exec"
property "sonar.coverage.exclusions", coverageExclusions
}
}
Jacoco config on (app/build.gradle)
def coverageExclusions = ['**/AEWatchApp.*', '**/**_Factory.*',
'**/QaSettingsActivity.*',
'com/aetn/android/tveapps/activities/**',
'com/aetn/android/tveapps/test/**',
'com/aetn/android/tveapps/app/injection/modules/**',
'com/aetn/android/tveapps/app/injection/components/**',
'com.aetn.android.tveapps.mock/**',
'com/aetn/android/tveapps/databinding/**']
jacocoAndroidUnitTestReport {
csv.enabled false
html.enabled true
xml.enabled true
excludes += coverageExclusions
}
As far as I can see branch coverage is the same: 40% in both cases, 15 uncovered.
And comparison of "instructions" (shown in screenshot of JaCoCo report) with anything else is like comparison of apples and oranges - they don't represent the same thing. See http://www.eclemma.org/jacoco/trunk/doc/counters.html about counters that JaCoCo provides. And https://docs.sonarqube.org/latest/user-guide/metric-definitions about what SonarQube shows. Instructions coverage is presented only in JaCoCo.
"lines" ("27.1%" shown in screenshot of SonarQube) is not the same as "instructions": Single line of code usually contains many bytecode instructions. So for example if in total you have 100 instructions in 10 lines and cover 1 line with 20 instructions, then missed instructions 80%, but missed lines 90%.
So all in all, there is no discrepancy or at least it is not shown on your screenshots.
I am building an application using Gradle, JDK 8, Java FX, and Test FX. I need to be on JDK 8 for our application to work on all platforms with our tech stack. My problem is that I am unable to get code coverage into our build. I found this link...
https://github.com/jacoco/jacoco/issues/74
...and using the Jacoco preview build at the top, I was able to replace my intellij JARs and successfully run my tests and get the coverage. However, I am having trouble putting this into my build.gradle. From what I can tell, I need to add a local repository in my build script...
...
apply plugin: "jacoco"
...
buildscript {
repositories {
// Local Repo
// MVN Repo(s)
}
dependencies {
// Classpaths
}
}
jacoco {
toolVersion = "0.6.4.201311160552" // I need this specific version, which isn't on a MVN repo
}
...I tried to add my local repo several ways including...
flatDir(dirs: "lib")
flatDir dirs: "${projectDir}/lib"
maven { url uri("lib") }
one or two other ways I forget
...my lib folder contains the exact contents, unchanged, from the preview build zip's lib folder in the link above. It doesn't seem like gradle is having a problem locating the local repo, but it is having trouble finding the JAR. I assume there is something wrong with the way I am naming it or the way that it is "packaged". I have tried modifying the JAR names but I keep getting the error...
What went wrong:
A problem occurred configuring root project 'myProject'.
Could not resolve all dependencies for configuration ':classpath'.
Could not find :org.jacoco.agent:.
Required by:
:myProject:unspecified
...any ideas why my JAR is not being found? Thanks!
"Answering" my own question, despite the fact that I still haven't quite figured it out. Anyways, here are two links I found that seem to solve my problem...
http://forums.gradle.org/gradle/topics/jacocotestreport_is_skipping
...following some of these instructions allow my tests to run, but I am still not able to run "gradle jacocoTestReport" without it failing.
UPDATE
OKAY! I figured it out, the link above did help me figure it out. My problem was with the asm-all JAR, since there were several, I did not know which one to use. In order to get jacoco working with Java 1.8, you do not need to specify the toolVersion property. All you need to do is add the following to your dependencies block (not the buildscript block, the code block)...
jacocoAgent files(
"$projectDir/lib/org.jacoco.agent-0.6.4.201311160552.jar")
jacocoAnt files(
"$projectDir/lib/org.jacoco.ant-0.6.4.201311160552.jar",
"$projectDir/lib/org.jacoco.core-0.6.4.201311160552.jar",
"$projectDir/lib/org.jacoco.report-0.6.4.201311160552.jar",
"$projectDir/lib/asm-all-5.0_BETA.jar")
...where the asm-all-5.0_BETA.jar is taken from the org.ow2.asm group found at...
http://mvnrepository.com/artifact/org.ow2.asm/asm-all/5.0_BETA
...hope this helps!
for reference, latest jacoco libs are changed so i'm sharing the following snippet:
dependencies{
jacocoAgent files("$rootProject.projectDir/lib/org.jacoco.agent-0.8.3.201904130250.jar")
jacocoAnt files("$rootProject.projectDir/lib/org.jacoco.ant-0.8.3.201904130250.jar",
"$rootProject.projectDir/lib/org.jacoco.core-0.8.3.201904130250.jar",
"$rootProject.projectDir/lib/org.jacoco.report-0.8.3.201904130250.jar",
"$rootProject.projectDir/lib/asm-7.0.jar",
"$rootProject.projectDir/lib/asm-tree-7.0.jar",
"$rootProject.projectDir/lib/asm-commons-7.0.jar"
)
}
I have very successfully integrated Gradle (1.11), Sonar ( 4.1.1 ), Java, Scala and Jacoco in my build process. I even managed to get info regarding the number of successful tests ( thanks to Stackoverflow! ). I have one problem though.
I can't seem to get info about coverage per test. It would be very nice to have this info.
> 15:11:16.514 INFO - Sensor JaCoCoSensor... 15:11:16.535 INFO -
> Analysing C:\example\gradle-sonar-jacoco-scala\build\jacoco\test.exec
> 15:11:17.887 INFO - No information about coverage per test.
A simplified version of the project is at : https://github.com/sebastianharko/gradle-sonar-java-jacoco-scalatest-junit
Cheers !
It Looks like you already have
apply plugin: 'jacoco'
in your gradle.build
But i'm not seeing a definition to where it's to get it file from in the gradle.build
jacoco {
destinationFile = file("$buildDir/jacoco/test.exec")
}
If you plan on doing integration and unit testing it would look similar to the following:
task "integtest"(type: Test, dependsOn: integtestClasses) {
testClassesDir = sourceSets.integtest.output.classesDir
classpath = sourceSets.integtest.runtimeClasspath
jacoco {
destinationFile = file("$buildDir/jacoco/integTest.exec")
}
}
test {
jacoco {
destinationFile = file("$buildDir/jacoco/test.exec")
}
}
With the corresponding sonar configuration items
property "sonar.jacoco.reportPath", "$buildDir/jacoco/test.exec"
property "sonar.jacoco.itReportPath", "$buildDir/jacoco/integTest.exec"
I've seen another conf parameters from SonarQube - integrationTest.exec - sonarRunner (Gradle) or "sonar-runner" command - showing 0.0% covereage :
The parameter sonar.java.coveragePlugin=jacoco called my attention. Did you try that?
You may also want to use Coveralls.io
It's very cheap: only $4.99/mo. and you would have a deep integration with your pull requests on Github (track when a branch increases or decreases your code coverage) as well as a very nice UI to drill down into your code coverage.
Both SBT and Gradle integrations are available.