TODO: link build status
TODO: link latest release
Jacoco Coverage is a Gradle Plugin that provides two tasks extending the standard Gradle Jacoco plugin:
- Firstly, the
org.wrlyonsjr.jacoco-coverage
plugin allows Gradle build scripts to configure minimum Java Code Coverage thresholds for projects, packages, classes, and files. - Secondly, the
org.wrlyonsjr.jacoco-full-report
plugin adds a task that produces a Jacoco report for the combined code coverage of the tests of all subprojects of the current project.
TODO: link changelog
Source code: https://github.com/wrlyonsjr/gradle-aggregate-jacoco
Add the following configuration to build.gradle
:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.wrlyonsjr:jacoco-coverage:<version>'
}
}
apply plugin: 'java'
apply plugin: 'org.wrlyonsjr.jacoco-coverage'
jacocoCoverage {
// Enforce minimum code coverage of 50% for every Java file.
fileThreshold 0.5
// Whitelist files named MyClass.java from coverage requirements.
fileThreshold 0.0, "MyClass.java"
}
Subsequent ./gradlew build
runs will fail if the configured minimum coverage thresholds are not achieved by the
project's tests. (Note that build
depends on check
which depends on the jacocoCoverage
task added by this plugin.)
Code coverage requirements are specified separately for the different "realms" reported by Jacoco:
- average coverage in a report, specified by the
reportThreshold
keyword - average coverage in a package, specified by the
packageThreshold
keyword - coverage in a class, specified by the
classThreshold
keyword - coverage in a file, specified by the
fileThreshold
keyword
Each realm contains a number of so-called "scopes":
- The file realm contains one scope for every source file, named by file name, e.g., "MyClass.java". Note that file scopes for files with the same name in different packages or folders clash; in such cases coverage thresholds should be specified in the class realm.
- The class realm contains one scope for every (top-level, inner, or anonymous) class, named by fully qualified class name, e.g., "org/package/MyClass$1".
- The package realm contains one scope for every package, named by the package name, e.g., "org/package".
- The report realm contains exactly one scope which is usually derived from the name of the corresponding Gradle (sub-) project.
Scopes can be specified by exact name, e.g., "MyClass.java"
, or by a Groovy regex pattern matching an arbitrary number
of scopes, e.g., ~'org/package.*'
for all sub-packages of "org/mypackage".
Coverage requirements are written in terms of a realm, a scope specification, and one (or several) of the Jacoco-defined types of coverage, e.g., lines covered or branches covered. The following syntax variations are supported:
<realm> <threshold>
<realm> <threshold>, <coverage type>
<realm> <threshold>, <scope name>
<realm> <threshold>, <coverage type>, <scope name>
<realm> <threshold>, <scope pattern>
<realm> <threshold>, <coverage type>, <scope pattern>
, where:
<realm>
is one offileThreshold
,classThreshold
,packageThreshold
,reportThreshold
<threshold>
is a Groovydouble
<coverage type>
is one ofBRANCH
,CLASS
,COMPLEXITY
,INSTRUCTION
,LINE
,METHOD
<scope name>
is a Groovy string<scope pattern>
is a Groovy regex pattern
Examples:
jacocoCoverage {
// Minimum code coverage of 50% for all scopes in the file realm (i.e., for all files) and for all coverage types.
fileThreshold 0.5
// Minimum 'branch' coverage of 30% for all files.
fileThreshold 0.3, BRANCH
// Minimum 'line' coverage of 10% for files (in any directory) whose name matches the given regular expression.
fileThreshold 0.1, LINE, ~"(Indentation|Wrapping)\\.java"
// Minimum 'line' coverage of 10% for files named "Indentation.java" (case-sensitive, in any directory).
// (Note: This syntax uses exact string match against the file name while the regex syntax requires escaping.)
fileThreshold 0.1, LINE, "Indentation.java"
// Minimum coverage of 30% in the given class.
classThreshold 0.3, "org/company/module/MyClass"
// Minimum average coverage of 30% in given package.
packageThreshold 0.3, "org/company/module"
// Minimum average coverage of 50% in report "my-project; the report name is usually the Gradle project name.
reportThreshold 0.5, "my-project"
// Scopes can be exempt from all coverage requirements by exact scope name or scope name pattern.
fileThreshold 0.0, "MyClass.java"
packageThreshold 0.0, "org/company/module"
fileThreshold 0.0, ~".*Test.java"
}
Given the observed code coverage for a realm, scope, and coverage type (e.g., line coverage 47% for class
org/product/module/MyClass
), the lowest specified threshold matching the scope and coverage type is enforced. For
example, the specification
jacocoCoverage {
classThreshold 0.5, BRANCH
classThreshold 0.3, "org/company/module/MyClass"
}
will enforce 50% branch coverage for every class, and 30% coverage for class org/company/module/MyClass
for all
coverage types. In particular, branch coverage for org/company/module/MyClass
is required to be at least 30% rather
than 50% since the lowest specified threshold dominates. This implies that specific coverage types and scopes can be
excluded from any thresholds globally, for example:
jacocoCoverage {
packageThreshold 0.0, BRANCH // Never enforce branch coverage at the package level
fileThreshold 0.0, ~".*Util\\.java" // Never enforce coverage on Java files like XyzUtil.java
packageThreshold 0.0, ~"org/thirdparty/.*" // Never enforce coverage on thirdparty package.
}
Add the following configuration to the build.gradle
configuration of the root project:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.wrlyonsjr:jacoco-coverage:<version>'
}
}
apply plugin: 'org.wrlyonsjr.jacoco-full-report' // Automatically applies the 'jacoco' plugin to this project.
Subsequent ./gradlew test jacocoFullReport
runs will generate a test report in build/reports/jacoco/jacocoFullReport/
that evaluates the coverage yielded by all subprojects combined. (Note that generally Jacoco reports are only generated
if the test
task has run previously in order to generated the Jacoco execution data.)
The jacocoFullReport
task is a standard JacocoReport
task and has the same configuration options as the vanilla
Gradle Jacoco task.
By default, Jacoco report tasks of all projects and subprojects are considered when compiling the full report. Projects
can be excluded from consideration through the jacocoFull
extension:
jacocoFull {
excludeProject ":my-sub-project", ":buildSrc"
}
Note that org.wrlyonsjr.jacoco-full-report
and org.wrlyonsjr.jacoco-coverage
can be combined in order to enforce
coverage requirements over the combined coverage of several subprojects.