Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce task for JaCoCo plugin for enforcing code coverage metrics #983

Merged
merged 42 commits into from Dec 21, 2016
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
313367a
Basic support for enforcing Jacoco metrics
Dec 2, 2016
d7f3b7d
Add test cases for multiple report tasks
Dec 2, 2016
3f50fcd
Add test case for multiple rules
Dec 2, 2016
5c3a8ad
Break out method
Dec 2, 2016
c27a0b2
Expose configuration option for disabling rules
Dec 2, 2016
3f971f7
Rules can be checked even if all report formats are disabled
Dec 2, 2016
2c7be9f
Use strong typing for enums
Dec 2, 2016
530828f
Rename of method
Dec 2, 2016
493e282
Add some unit tests
Dec 2, 2016
317ec14
Renamed property
Dec 2, 2016
5b0f085
Set default values for fields as described in Jacoco docs
Dec 2, 2016
f8f3070
Renamed fields to better express intention
Dec 2, 2016
9b5ed0a
Rename field
Dec 2, 2016
358a6f9
Enhance samples and documentation
Dec 5, 2016
a73a193
Better IDE support for Closure parameters
Dec 5, 2016
6627b49
Bump up version number
Dec 5, 2016
8e6d20c
Use String data type instead of enum
Dec 5, 2016
70b0f0a
Align terminology with Jacoco configuration options
Dec 5, 2016
aed27f6
Apply input/output annotations
Dec 6, 2016
00b2cb3
Document default value for property
Dec 6, 2016
0dc8b31
Verify proper behavior of Ant task for unknown values
Dec 6, 2016
45674bd
Remove spaces
Dec 6, 2016
ebb4d11
Add multi-version coverage for check support
Dec 6, 2016
41dcf72
Reuse version number across all multi-version tests
Dec 6, 2016
0521afb
Add missing word
Dec 6, 2016
6c63ff9
Use constant for task paths
Dec 6, 2016
db94948
Extract dedicated task for verifying if coverage metrics are met
Dec 6, 2016
f024a94
Input annotation make sure that requires properties are not null
Dec 6, 2016
aa402c8
Reflect use of JacocoCheck task in documentation and sample
Dec 7, 2016
08882e9
Revert change
Dec 7, 2016
6b1f8d9
Use JacocoCheck in documentation
Dec 7, 2016
1eb517c
Reuse task logic for JacocoReport and JacocoCheck
Dec 7, 2016
8d06c8f
Fix indentation
Dec 7, 2016
699a622
Reuse logic
Dec 7, 2016
47feb94
Move logic into parent class
Dec 7, 2016
8097fdd
Task is not cacheable as it doesn't declare outputs
Dec 7, 2016
ff77afc
Ignore running tests on Java 9
Dec 20, 2016
1e31712
Report task should fail if any of the input file does not exist
Dec 20, 2016
a7a4592
Assign group and description for tasks
Dec 20, 2016
d900795
Use task name that better expresses intent
Dec 20, 2016
d832d0d
Change targeted release version
Dec 20, 2016
ec1b003
Fix task name in sample project
Dec 20, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,43 @@
<!--
~ Copyright 2016 the original author or authors.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<section>
<section>
<title>Properties</title>
<table>
<thead>
<tr>
<td>Name</td>
<td>Default with <literal>jacoco</literal> plugin</td>
</tr>
</thead>
<tr>
<td>violationRules</td>
<td/>
</tr>
</table>
</section>
<section>
<title>Methods</title>
<table>
<thead>
<tr>
<td>Name</td>
</tr>
</thead>
</table>
</section>
</section>
Expand Up @@ -21,32 +21,9 @@
<thead>
<tr>
<td>Name</td>
<td>Default with
<literal>jacoco</literal>
plugin
</td>
<td>Default with <literal>jacoco</literal> plugin</td>
</tr>
</thead>
<tr>
<td>executionData</td>
<td/>
</tr>
<tr>
<td>sourceDirectories</td>
<td/>
</tr>
<tr>
<td>classDirectories</td>
<td/>
</tr>
<tr>
<td>additionalClassDirs</td>
<td/>
</tr>
<tr>
<td>additionalSourceDirs</td>
<td/>
</tr>
<tr>
<td>reports</td>
<td/>
Expand All @@ -61,9 +38,6 @@
<td>Name</td>
</tr>
</thead>
<tr>
<td>executionData</td>
</tr>
</table>
</section>
</section>
@@ -0,0 +1,62 @@
<!--
~ Copyright 2016 the original author or authors.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<section>
<section>
<title>Properties</title>
<table>
<thead>
<tr>
<td>Name</td>
<td>Default with <literal>jacoco</literal> plugin</td>
</tr>
</thead>
<tr>
<td>executionData</td>
<td/>
</tr>
<tr>
<td>sourceDirectories</td>
<td/>
</tr>
<tr>
<td>classDirectories</td>
<td/>
</tr>
<tr>
<td>additionalClassDirs</td>
<td/>
</tr>
<tr>
<td>additionalSourceDirs</td>
<td/>
</tr>
</table>
</section>
<section>
<title>Methods</title>
<table>
<thead>
<tr>
<td>Name</td>
</tr>
</thead>
<tr>
<td>executionData</td>
</tr>
</table>
</section>
</section>
36 changes: 36 additions & 0 deletions subprojects/docs/src/docs/userguide/jacocoPlugin.xml
Expand Up @@ -81,6 +81,32 @@
</imageobject>
</section>

<section id="sec:jacoco_report_violation_rules">
<title>Enforcing code coverage metrics</title>
<note>
<para>
This feature requires the use of JaCoCo version 0.6.3 or higher.
</para>
</note>
<para>
The <apilink class="org.gradle.testing.jacoco.tasks.JacocoCheck"/> task can be used to verify if code coverage
metrics are met based on configured rules. Its API exposes two methods,
<apilink class="org.gradle.testing.jacoco.tasks.JacocoCheck" method="violationRules(groovy.lang.Closure)"/> and
<apilink class="org.gradle.testing.jacoco.tasks.JacocoCheck" method="violationRules(org.gradle.api.Action)"/>,
the main entry point for configuring rules.
Invoking any of those methods returns an instance of <apilink class="org.gradle.testing.jacoco.tasks.rules.JacocoViolationRulesContainer"/> providing
extensive configuration options. The build fails if any of the configured rules are not met. JaCoCo only reports the first violated rule.
</para>
<para>
Code coverage requirements can be specified for a project as a whole, for individual files, and for
particular JaCoCo-specific types of coverage, e.g., lines covered or branches covered. The following example
describes the syntax.
</para>
<sample id="configViolationRules" dir="testing/jacoco/quickstart" title="Configuring violation rules">
<sourcefile file="build.gradle" snippet="violation-rules-configuration"/>
</sample>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any Jacoco docs we could link to too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment above.

</section>

<section id="sec:jacoco_specific_task_configuration">
<title>JaCoCo specific task configuration</title>
<para>The JaCoCo plugin adds a
Expand Down Expand Up @@ -215,6 +241,16 @@
</td>
<td>Generates code coverage report for the test task.</td>
</tr>
<tr>
<td>
<literal>jacocoTestCheck</literal>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: this task name doesn't represent what it's for IMO. Perhaps jacocoVerificationCheck or jacocoEnforceThresholds or something.

</td>
<td>-</td>
<td>
<apilink class="org.gradle.testing.jacoco.tasks.JacocoCheck"/>
</td>
<td>Verifies code coverage metrics based on specified rules for the test task.</td>
</tr>
</table>
</section>

Expand Down
Expand Up @@ -56,3 +56,27 @@ jacocoTestReport {
}
}
// END SNIPPET report-configuration

// START SNIPPET violation-rules-configuration
jacocoTestCheck {
violationRules {
rule {
limit {
minimum = 0.5
}
}

rule {
enabled = false
element = 'CLASS'
includes = ['org.gradle.*']

limit {
counter = 'LINE'
value = 'TOTALCOUNT'
maximum = 0.3
}
}
}
}
// END SNIPPET violation-rules-configuration
Expand Up @@ -18,31 +18,21 @@ package org.gradle.testing.jacoco.plugins

import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.LocalBuildCacheFixture
import org.gradle.testing.jacoco.plugins.fixtures.JavaProjectUnderTest
import org.gradle.util.Requires

import static org.gradle.util.TestPrecondition.FIX_TO_WORK_ON_JAVA9

@Requires(FIX_TO_WORK_ON_JAVA9)
class JacocoCachingIntegrationTest extends AbstractIntegrationSpec implements LocalBuildCacheFixture {

private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory)

def "jacoco file results are cached"() {
file("src/main/java/org/gradle/Class1.java") <<
"package org.gradle; public class Class1 { public boolean isFoo(Object arg) { return true; } }"
file("src/test/java/org/gradle/Class1Test.java") <<
"package org.gradle; import org.junit.Test; public class Class1Test { @Test public void someTest() { new Class1().isFoo(\"test\"); } }"
javaProjectUnderTest.writeBuildScript().writeSourceFiles()
def reportFile = file("build/reports/jacoco/test/html/index.html")

buildFile << """
apply plugin: "java"
apply plugin: "jacoco"

repositories {
mavenCentral()
}
dependencies {
testCompile 'junit:junit:4.12'
}

jacocoTestReport.dependsOn test

sourceSets.test.output.classesDir = file("build/classes/test")
Expand Down
Expand Up @@ -20,6 +20,7 @@ import org.gradle.api.Project
import org.gradle.api.reporting.ReportingExtension
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.executer.GradleContextualExecuter
import org.gradle.testing.jacoco.plugins.fixtures.JavaProjectUnderTest
import org.gradle.util.Requires
import spock.lang.IgnoreIf
import spock.lang.Issue
Expand All @@ -28,24 +29,14 @@ import static org.gradle.util.TestPrecondition.FIX_TO_WORK_ON_JAVA9

class JacocoPluginIntegrationTest extends AbstractIntegrationSpec {

private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory)
private static final String REPORTING_BASE = "${Project.DEFAULT_BUILD_DIR_NAME}/${ReportingExtension.DEFAULT_REPORTS_DIR_NAME}"
private static final String REPORT_HTML_DEFAULT_PATH = "${REPORTING_BASE}/jacoco/test/html/index.html"
private static final String REPORT_XML_DEFAULT_PATH = "${REPORTING_BASE}/jacoco/test/jacocoTestReport.xml"
private static final String REPORT_CSV_DEFAULT_REPORT = "${REPORTING_BASE}/jacoco/test/jacocoTestReport.csv"

def setup() {
buildFile << """
apply plugin: "java"
apply plugin: "jacoco"

repositories {
mavenCentral()
}
dependencies {
testCompile 'junit:junit:4.12'
}
"""
createTestFiles()
javaProjectUnderTest.writeBuildScript().writeSourceFiles()
}

def "jacoco plugin adds coverage report for test task when java plugin applied"() {
Expand Down Expand Up @@ -320,12 +311,5 @@ public class ThingTest {
private JacocoReportFixture htmlReport(String basedir = "${REPORTING_BASE}/jacoco/test/html") {
return new JacocoReportFixture(file(basedir))
}

private void createTestFiles() {
file("src/main/java/org/gradle/Class1.java") <<
"package org.gradle; public class Class1 { public boolean isFoo(Object arg) { return true; } }"
file("src/test/java/org/gradle/Class1Test.java") <<
"package org.gradle; import org.junit.Test; public class Class1Test { @Test public void someTest() { new Class1().isFoo(\"test\"); } }"
}
}

Expand Up @@ -17,35 +17,26 @@
package org.gradle.testing.jacoco.plugins

import org.gradle.integtests.fixtures.AbstractTaskRelocationIntegrationTest
import org.gradle.testing.jacoco.plugins.fixtures.JavaProjectUnderTest
import org.gradle.util.Requires

import static org.gradle.util.TestPrecondition.FIX_TO_WORK_ON_JAVA9

@Requires(FIX_TO_WORK_ON_JAVA9)
class JacocoReportRelocationIntegrationTest extends AbstractTaskRelocationIntegrationTest {

private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory)

@Override
protected String getTaskName() {
return ":jacocoTestReport"
}

@Override
protected void setupProjectInOriginalLocation() {
file("src/main/java/org/gradle/Class1.java") <<
"package org.gradle; public class Class1 { public boolean isFoo(Object arg) { return true; } }"
file("src/test/java/org/gradle/Class1Test.java") <<
"package org.gradle; import org.junit.Test; public class Class1Test { @Test public void someTest() { new Class1().isFoo(\"test\"); } }"
javaProjectUnderTest.writeBuildScript().writeSourceFiles()

buildFile << """
apply plugin: "java"
apply plugin: "jacoco"

repositories {
mavenCentral()
}
dependencies {
testCompile 'junit:junit:4.12'
}

sourceSets.test.output.classesDir = file("build/classes/test")
"""

Expand Down
Expand Up @@ -17,6 +17,7 @@
package org.gradle.testing.jacoco.plugins

import org.gradle.integtests.fixtures.AbstractTaskRelocationIntegrationTest
import org.gradle.testing.jacoco.plugins.fixtures.JavaProjectUnderTest
import org.gradle.util.Requires

import static org.gradle.util.BinaryDiffUtils.levenshteinDistance
Expand All @@ -25,29 +26,17 @@ import static org.gradle.util.TestPrecondition.FIX_TO_WORK_ON_JAVA9

@Requires(FIX_TO_WORK_ON_JAVA9)
class JacocoTestRelocationIntegrationTest extends AbstractTaskRelocationIntegrationTest {

private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory)

@Override
protected String getTaskName() {
return ":test"
}

@Override
protected void setupProjectInOriginalLocation() {
file("src/main/java/org/gradle/Class1.java") <<
"package org.gradle; public class Class1 { public boolean isFoo(Object arg) { return true; } }"
file("src/test/java/org/gradle/Class1Test.java") <<
"package org.gradle; import org.junit.Test; public class Class1Test { @Test public void someTest() { new Class1().isFoo(\"test\"); } }"

buildFile << """
apply plugin: "java"
apply plugin: "jacoco"

repositories {
mavenCentral()
}
dependencies {
testCompile 'junit:junit:4.12'
}
"""
javaProjectUnderTest.writeBuildScript().writeSourceFiles()
}

@Override
Expand Down