21

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.

Juan Pressacco
  • 313
  • 1
  • 2
  • 6

2 Answers2

20

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/

jivimberg
  • 840
  • 1
  • 10
  • 21
  • This is perfect. I kept trying to use excludes in the rule and failing to see any change. Thanks for figuring it out. Up voted! – AllanT Apr 30 '18 at 23:15
  • 9
    In Gradle 6 at least, this fails with the following: `Cannot set the value of read-only property 'classDirectories' for task ':jacocoTestCoverageVerification' of type org.gradle.testing.jacoco.tasks.JacocoCoverageVerification.` – tschumann Oct 28 '19 at 22:48
  • 2
    @tschumann replace classDirectories = files(classDirectories.files.collect TO getClassDirectories().setFrom(classDirectories.files.collect – Daniil Volkov Apr 08 '20 at 13:00
  • 1
    @DaniilVolkov is my hero. Thank you! – dazza5000 Apr 08 '20 at 23:10
  • 3
    In kotlin, you can do `classDirectories.setFrom( classDirectories.files.flatMap { fileTree(it) { exclude("**/App.class") } } ` – Karl Molina Sep 17 '21 at 21:03
  • use: for kotlin: ```classDirectories.setFrom(classDirectories.files.flatMap { fileTree(it) { include("**/service/**") } })``` instead of ```afterEvaluate {...}``` – DamienMiheev Oct 13 '21 at 13:51
15

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
MartinTeeVarga
  • 10,478
  • 12
  • 61
  • 98
  • BTW here's a gist of what I tried in my project (and it worked): https://gist.github.com/sm4/1cacc5d8b6d99cac84336ab4df06d1bd and this is the project: https://github.com/sm4/promo-codes – MartinTeeVarga Apr 04 '17 at 01:38
  • Yes you were right, I was trying to measure two differents things. Also I try with your configuration to add a check rule and it works. Thanks!! – Juan Pressacco Apr 05 '17 at 20:23