I want to make jacoco plugin to fail when test coverage is not enough. I use example from gradle page :
https://docs.gradle.org/current/userguide/jacoco_plugin.html
apply plugin: 'jacoco'
jacoco {
toolVersion = "0.7.6.201602180812"
reportsDir = file("output/jacoco/customJacocoReportDir")
}
jacocoTestReport {
reports {
xml.enabled false
csv.enabled false
html.enabled true
html.destination file("output/jacoco/jacocoHtml")
}
}
jacocoTestCoverageVerification {
violationRules {
rule {
limit {
minimum = 0.5
}
}
rule {
enabled = false
element = 'CLASS'
includes = ['org.gradle.*']
limit {
counter = 'LINE'
value = 'TOTALCOUNT'
maximum = 0.3
}
}
}
}
However, I get error:
Could not find method jacocoTestCoverageVerification() for arguments [build_4v41fim1xdl76q49oxk7mnylv$_run_closure6#18601994] on root project 'demo' of type org.gradle.api.Project.
Can anyone advise?
According to the the docs for Gradle version 3.4 or higher :
For projects that also apply the Java Plugin, The JaCoCo plugin automatically adds the following tasks:
jacocoTestReport [...]
jacocoTestCoverageVerification [...]
If the code block in your question shows your full build.gradle file, this would mean that you need to add the line that applies the Java Plugin (apply plugin: 'java').
Of course, you could also add a task of type JacocoCoverageVerification called jacocoTestCoverageVerification to your build file on your own:
task jacocoTestCoverageVerification(type: JacocoCoverageVerification) {
// configuration
}
Try using latest version of gradle. This may solve your problem
Related
Gradle Version: 6.1.1
Android Gradle Plugin: 4.0.0
When trying to run my jacoco coverage it does not appear to be taking into account the version. When I look at the HTML report it states "Created with JaCoCo 0.7.9.201702052155" despite me having toolVersion = "0.8.5" in my setup. The report also does not have fixes that I expect in 0.8.3 relating to Kotlin as a secondary confirmation this isn't working.
apply plugin: 'jacoco'
jacoco {
toolVersion = "0.8.5"
reportsDir = file("$buildDir/reports")
}
tasks.withType(Test) {
jacoco.includeNoLocationClasses = true
jacoco.excludes = ['jdk.internal.*']
}
project.afterEvaluate {
(android.hasProperty('applicationVariants')
? android.'applicationVariants'
: android.'libraryVariants').all { variant ->
def variantName = variant.name
def unitTestTask = "test${variantName.capitalize()}UnitTest"
def uiTestCoverageTask = "create${variantName.capitalize()}CoverageReport"
tasks.create(name: "${unitTestTask}Coverage", type: JacocoReport, dependsOn: [
"$unitTestTask",
"$uiTestCoverageTask"
]) {
group = "Reporting"
description = "Generate Jacoco coverage reports for the ${variantName.capitalize()} build"
reports {
html.enabled = true
xml.enabled = true
csv.enabled = false
}
def fileFilter = [
'**/R.class',
'**/R$*.class',
'**/BuildConfig.*',
'**/Manifest*.*',
'**/*Test*.*',
'**/com/example/databinding/*',
'**/com/example/generated/callback/*',
'**/android/databinding/*',
'**/androidx/databinding/*',
'**/di/module/*',
'**/*MapperImpl*.*',
'**/*$ViewInjector*.*',
'**/*$ViewBinder*.*',
'**/BuildConfig.*',
'**/*Component*.*',
'**/*BR*.*',
'**/Manifest*.*',
'**/*$Lambda$*.*',
'**/*Companion*.*',
'**/*Module.*',
'**/*Dagger*.*',
'**/*MembersInjector*.*',
'**/*_Factory*.*',
'**/*_Provide*Factory*.*',
'**/*Extensions*.*',
'**/*$Result.*', /* filtering `sealed` and `data` classes */
'**/*$Result$*.*'/* filtering `sealed` and `data` classes */
]
classDirectories.setFrom(files([
fileTree(dir: "${buildDir}/tmp/kotlin-classes/${variantName}", excludes: fileFilter)
]))
def coverageSourceDirs = [
"$project.rootDir/app/src/main/java",
"$project.projectDir/src/${variantName}/java"
]
additionalSourceDirs.setFrom(files(coverageSourceDirs))
sourceDirectories.setFrom(files(coverageSourceDirs))
def uiTestsData = fileTree(dir: "${buildDir}/outputs/code_coverage/${variantName}AndroidTest/connected/", includes: ["**/*.ec"])
executionData(files([
"$project.buildDir/jacoco/${unitTestTask}.exec",
uiTestsData
]))
}
}
}
As stated from #Bilgehan KALKAN here, as of Gradle 7, this seems to be resolved.
android {
//Other configurations...
testCoverage.jacocoVersion = "0.8.7"
}
For lower gradle version try adding this to your Project Gradle file.
subprojects {
configurations.all {
resolutionStrategy {
eachDependency { details ->
if ('org.jacoco' == details.requested.group) {
details.useVersion "0.8.6"
}
}
}
}
}
You don't need to override version as mentioned on #LethalMaus's answer. You only need to specify jacoco version under android as testCoverage.jacocoVersion, jacoco.version approach on #Alexy Nikitin's answer has been deprecated and replaced with testCoverage.jacocoVersion.
If you do not specify any version, it will use DEFAULT_VERSION under JacocoOptions class. Which is "0.8.3" for Android Gradle Plugin version 7.0.2.
You should declare jacoco version in the android gradle plugin too:
android {
jacoco {
version "<your jacoco version>"
}
}
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.
I have a Corda based project with several CorDapp sub projects. I've been looking to add JaCoCo code coverage to this project. I'm looking to have a single code coverage report draw in an aggregate report of all the subproject JaCoCo reports.
To add JaCoCo to a maven project with several maven sub projects, I followed this blog entry https://lkrnac.net/blog/2016/10/aggregate-test-coverage-report/. After we ran the build ./gradlew clean test and got our reports, one of our team members noted that the whitelists weren't being created properly anymore when we ran ./gradlew clean deployNodes.
I've gone back to the base Kotlin CorDapp template found here https://github.com/corda/cordapp-template-kotlin to rule out if it's something we've done wrong with our project structure/gradle. Without JaCoCo added, I see all the whitelist entries I would expect. Once I add the JaCoCo code, I only see the 5 default Corda whitelist entries, and none of my added contract entries.
I'm using JaCoCo version 0.8.1 and coveralls version 2.6.3. The changes I've made are all within the build.gradle file for the root directory cordapp-template-kotlin:
subprojects {
repositories {
mavenCentral()
}
apply plugin: 'jacoco'
apply plugin: 'java'
group = 'net.lkrnac.blog'
version = '1.0-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
dependencies {
testCompile("junit:junit:4.12")
}
jacoco {
toolVersion = jacoco_version
}
//command for generating subproject coverage reports
jacocoTestReport {
reports {
xml.enabled false
csv.enabled false
html.destination file("${buildDir}/jacocoHtml")
}
}
}
def publishedProjects = subprojects.findAll()
task jacocoRootReport(type: JacocoReport, group: 'Coverage reports') {
description = 'Generates an aggregate report from all subprojects'
dependsOn(publishedProjects.test)
additionalSourceDirs = files(publishedProjects.sourceSets.main.allSource.srcDirs)
sourceDirectories = files(publishedProjects.sourceSets.main.allSource.srcDirs)
classDirectories = files(publishedProjects.sourceSets.main.output)
executionData = files(publishedProjects.jacocoTestReport.executionData)
doFirst {
executionData = files(executionData.findAll { it.exists() })
}
reports {
html.enabled = true // human readable
xml.enabled = true // required by coveralls
}
}
coveralls {
sourceDirs = publishedProjects.sourceSets.main.allSource.srcDirs.flatten()
jacocoReportPath = "${buildDir}/reports/jacoco/jacocoRootReport/jacocoRootReport.xml"
}
tasks.coveralls {
dependsOn jacocoRootReport
}
I believe that the problem is coming from simply adding a task where JacocoReport as a parameter. Any thoughts how I could proceed to have both code coverage, along with building my whitelists correctly?
I have managed to find how to fix the coverage/whitelisting issue. I started stripping away what seemed to be unnecessary code within the subprojects spec, and found that removing everything except the apply plugin:, jacoco, and jacocoTestReport commands yielded both the root Jacoco code coverage, along with the necessary whitelisting. I didn't need to change any of the other code above to get the whitelisting to work.
For reference, subprojects now looks like this:
subprojects {
apply plugin: 'jacoco'
apply plugin: 'kotlin'
jacoco {
toolVersion = jacoco_version
}
//command for generating subproject coverage reports
jacocoTestReport {
reports {
xml.enabled false
csv.enabled false
html.destination file("${buildDir}/jacocoHtml")
}
}
}
I need to check the minimum coverage with the new jacoco task
jacocoTestCoverageVerification
This task is available with in the 3.4.1 gradle release and with the jacoco plugin >= 0.6.3
I could run another task that generates an html report with the branch coverage but now I want to use that number to make the build fail.
This is my code
buildscript {
ext {
....
}
repositories {
mavenCentral()
maven {
....
}
}
dependencies {
.....
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'jacoco'
jar {
baseName = "coverage-test"
}
dependencies {
// my dependencies
}
eclipse {
classpath {
containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8'
}
}
wrapper {
gradleVersion = '3.4.1'
}
jacoco {
toolVersion = '0.7.9'
}
jacocoTestReport {
reports {
xml.enabled false
csv.enabled false
}
group = "Reporting"
description = "Generate Jacoco coverage reports after running tests."
additionalSourceDirs = files(sourceSets.main.allJava.srcDirs)
afterEvaluate {
classDirectories = files(classDirectories.files.collect {
fileTree(
dir: it,
excludes:
[
'com/jacoco/dto/**',
'com/jacoco/configs/**',
//and others
])
})
}
}
jacocoTestCoverageVerification {
//I tried this and it didn't work
// classDirectories = files(classDirectories.files.collect {
// fileTree(
// dir: it,
// excludes:
// [
// 'com/jacoco/dto/**',
// 'com/jacoco/configs/**',
// //and others
// ])
// })
violationRules {
rule {
//Also tried this and it didn't work
// excludes = ['com/jacoco/dto/**', ...]
limit {
counter = 'BRANCH'
minimum = 0.8
}
}
}
}
check.dependsOn jacocoTestCoverageVerification
With classDirectories I get the following error Cannot get property 'files' on null object. And with the second option (only excludes), the build run smoothly but It doesn't exclude any class.
In my case I did wanted to use the BUNDLE scope to set a threshold for the whole while excluding certain packages and files.
What worked for me in the end was adding the classDirectories exclude, as suggested in the original question, but inside afterEvaluate like this:
afterEvaluate {
classDirectories = files(classDirectories.files.collect {
fileTree(dir: it, exclude: [
'com/example/my/package/*',
'com/example/service/MyApplication.class',
'com/google/protobuf/*'
])
})
}
For reference the complete build.gradle looks like this:
apply plugin: "jacocoā€¯
jacocoTestCoverageVerification {
afterEvaluate {
getClassDirectories().setFrom(classDirectories.files.collect {
fileTree(dir: it, exclude: [
'com/example/my/package/*',
'com/example/service/MyApplication.class',
'com/google/protobuf/*'
])
})
}
violationRules {
rule {
limit {
minimum = 0.79
}
}
}
}
// to run coverage verification during the build (and fail when appropriate)
check.dependsOn jacocoTestCoverageVerification
You can find more details in my blog: http://jivimberg.io/blog/2018/04/26/gradle-verify-coverage-with-exclusions/
You are measuring a different thing that you are excluding. The default JaCoCo scope is "BUNDLE" which I believe means the whole code. I've never used that. I always measure only "CLASS" scope. And it looks like you are trying to do the same.
The excludes are relative to the elements in the scope. Not sure what it means for "BUNDLE", but I am almost inclined to think it's either all or nothing. Also the excludes use different type of wildcard. Try changing your configuration to use element "CLASS" (or "PACKAGE").
violationRules {
rule {
element = 'CLASS'
excludes = ['com.jacoco.dto.*']
limit {
counter = 'BRANCH'
minimum = 0.8
}
}
}
check.dependsOn jacocoTestCoverageVerification
I am trying to configure findbugs in my project with
findbugs {
ignoreFailures = true
reports {
html { enabled = true }
xml.enabled = !html.enabled
}
}
but an error appears
Could not find method reports() for arguments
[quality_4gppo4hjtn3ur86ac71a18pai6$_run_closure2_closure4#6651ccf]
on root project 'Project'.
This code was used in one of my previous projects with Gradle 1.7 and it was working.
You can use the reports method on a FindBugs task. The findbugs plugin creates one for every source set. So if you want to use FindBugs on your main classes, you would use
findbugsMain {
ignoreFailures = true
reports {
html { enabled = true }
xml.enabled = !html.enabled
}
}
If you want to configure all the findbugs tasks the same way, then you can simply apply the same configuration to all of them:
tasks.withType(FindBugs) {
ignoreFailures = true
reports {
html { enabled = true }
xml.enabled = !html.enabled
}
}