Skip to content

Commit 7c2e35a

Browse files
Albert Meltzerkitbellew
Albert Meltzer
authored andcommitted
Coverage minima: add more fine-grained control
Along with existing statement minimum, add branch minimum. Also, include this pair of control at the package and file level.
1 parent e81c12d commit 7c2e35a

File tree

2 files changed

+118
-24
lines changed

2 files changed

+118
-24
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,12 @@ Read [SBT SCoverage Plugin documentation](https://github.com/scoverage/sbt-scove
335335
<artifactId>scoverage-maven-plugin</artifactId>
336336
<version>${scoverage.plugin.version}</version>
337337
<configuration>
338-
<minimumCoverage>80</minimumCoverage>
338+
<minimumCoverage>95</minimumCoverage>
339+
<minimumCoverageBranchTotal>90</minimumCoverageBranchTotal>
340+
<minimumCoverageStmtPerPackage>90</minimumCoverageStmtPerPackage>
341+
<minimumCoverageBranchPerPackage>85</minimumCoverageBranchPerPackage>
342+
<minimumCoverageStmtPerFile>85</minimumCoverageStmtPerFile>
343+
<minimumCoverageBranchPerFile>80</minimumCoverageBranchPerFile>
339344
<failOnMinimumCoverage>true</failOnMinimumCoverage>
340345
</configuration>
341346
<executions>

src/main/java/org/scoverage/plugin/SCoverageCheckMojo.java

Lines changed: 112 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import org.apache.maven.plugin.AbstractMojo;
2525
import org.apache.maven.plugin.MojoFailureException;
26+
import org.apache.maven.plugin.logging.Log;
2627
import org.apache.maven.plugins.annotations.Execute;
2728
import org.apache.maven.plugins.annotations.LifecyclePhase;
2829
import org.apache.maven.plugins.annotations.Mojo;
@@ -33,6 +34,10 @@
3334
import scala.jdk.javaapi.CollectionConverters;
3435

3536
import scoverage.domain.Coverage;
37+
import scoverage.domain.CoverageMetrics;
38+
import scoverage.domain.DoubleFormat;
39+
import scoverage.domain.MeasuredFile;
40+
import scoverage.domain.MeasuredPackage;
3641
import scoverage.reporter.IOUtils;
3742
import scoverage.serialize.Serializer;
3843

@@ -70,7 +75,7 @@ public class SCoverageCheckMojo
7075
private File dataDirectory;
7176

7277
/**
73-
* Required minimum coverage.
78+
* Required minimum total statement coverage.
7479
* <br>
7580
* <br>
7681
* See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
@@ -81,6 +86,56 @@ public class SCoverageCheckMojo
8186
@Parameter( property = "scoverage.minimumCoverage", defaultValue = "0" )
8287
private Double minimumCoverage;
8388

89+
/**
90+
* Required minimum total branch coverage.
91+
* <br>
92+
* <br>
93+
* See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
94+
* <br>
95+
*/
96+
@Parameter( property = "scoverage.minimumCoverageBranchTotal", defaultValue = "0" )
97+
private Double minimumCoverageBranchTotal;
98+
99+
/**
100+
* Required minimum per-package statement coverage.
101+
* <br>
102+
* <br>
103+
* See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
104+
* <br>
105+
*/
106+
@Parameter( property = "scoverage.minimumCoverageStmtPerPackage", defaultValue = "0" )
107+
private Double minimumCoverageStmtPerPackage;
108+
109+
/**
110+
* Required minimum per-package branch coverage.
111+
* <br>
112+
* <br>
113+
* See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
114+
* <br>
115+
*/
116+
@Parameter( property = "scoverage.minimumCoverageBranchPerPackage", defaultValue = "0" )
117+
private Double minimumCoverageBranchPerPackage;
118+
119+
/**
120+
* Required minimum per-file statement coverage.
121+
* <br>
122+
* <br>
123+
* See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
124+
* <br>
125+
*/
126+
@Parameter( property = "scoverage.minimumCoverageStmtPerFile", defaultValue = "0" )
127+
private Double minimumCoverageStmtPerFile;
128+
129+
/**
130+
* Required minimum per-file branch coverage.
131+
* <br>
132+
* <br>
133+
* See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
134+
* <br>
135+
*/
136+
@Parameter( property = "scoverage.minimumCoverageBranchPerFile", defaultValue = "0" )
137+
private Double minimumCoverageBranchPerFile;
138+
84139
/**
85140
* Fail the build if minimum coverage was not reached.
86141
* <br>
@@ -172,27 +227,23 @@ public void execute() throws MojoFailureException
172227
getLog().info( String.format( "Branch coverage....: %s%%", coverage.branchCoverageFormatted() ) );
173228
getLog().debug( String.format( "invokedBranchesCount:%d / branchCount:%d, invokedStatementCount:%d / statementCount:%d",
174229
invokedBranchesCount, branchCount, invokedStatementCount, statementCount ) );
175-
if ( minimumCoverage > 0.0 )
230+
231+
boolean ok = checkCoverage( getLog(), "Total", coverage,
232+
minimumCoverage, minimumCoverageBranchTotal );
233+
for ( MeasuredPackage pkgCoverage : CollectionConverters.asJava( coverage.packages() ) )
176234
{
177-
String minimumCoverageFormatted = scoverage.domain.DoubleFormat.twoFractionDigits( minimumCoverage );
178-
if ( is100( minimumCoverage ) && is100( coverage.statementCoveragePercent() ) )
179-
{
180-
getLog().info( "100% Coverage !" );
181-
}
182-
else if ( coverage.statementCoveragePercent() < minimumCoverage )
183-
{
184-
getLog().error( String.format( "Coverage is below minimum [%s%% < %s%%]",
185-
coverage.statementCoverageFormatted(), minimumCoverageFormatted ) );
186-
if ( failOnMinimumCoverage )
187-
{
188-
throw new MojoFailureException( "Coverage minimum was not reached" );
189-
}
190-
}
191-
else
192-
{
193-
getLog().info( String.format( "Coverage is above minimum [%s%% >= %s%%]",
194-
coverage.statementCoverageFormatted(), minimumCoverageFormatted ) );
195-
}
235+
ok &= checkCoverage( getLog(), "Package:" + pkgCoverage.name(), pkgCoverage,
236+
minimumCoverageStmtPerPackage, minimumCoverageBranchPerPackage );
237+
}
238+
for ( MeasuredFile fileCoverage : CollectionConverters.asJava( coverage.files() ) )
239+
{
240+
ok &= checkCoverage( getLog(), "File:" + fileCoverage.filename(), fileCoverage,
241+
minimumCoverageStmtPerFile, minimumCoverageBranchPerFile );
242+
}
243+
244+
if ( !ok && failOnMinimumCoverage )
245+
{
246+
throw new MojoFailureException( "Coverage minimum was not reached" );
196247
}
197248

198249
long te = System.currentTimeMillis();
@@ -201,9 +252,47 @@ else if ( coverage.statementCoveragePercent() < minimumCoverage )
201252

202253
// Private utility methods
203254

204-
private boolean is100( Double d )
255+
private static boolean is100( Double d )
205256
{
206257
return Math.abs( 100 - d ) <= 0.00001d;
207258
}
208259

209-
}
260+
private static boolean checkCoverage( Log logger, String metric, CoverageMetrics metrics,
261+
double minimumStmt, double minimimBranch )
262+
{
263+
return
264+
checkCoverage( logger, "Statement:" + metric, minimumStmt, metrics.statementCoveragePercent() ) &&
265+
checkCoverage( logger, "Branch:" + metric, minimimBranch, metrics.branchCoveragePercent() );
266+
}
267+
268+
private static boolean checkCoverage( Log logger, String metric, double minimum, double actual )
269+
{
270+
if ( minimum <= 0 )
271+
{
272+
return true;
273+
}
274+
275+
if ( is100( minimum ) && is100( actual ) )
276+
{
277+
logger.debug( String.format( "Coverage is 100%: %s!", metric ));
278+
return true;
279+
}
280+
281+
String minimumFormatted = DoubleFormat.twoFractionDigits( minimum );
282+
String actualFormatted = DoubleFormat.twoFractionDigits( actual );
283+
boolean ok = minimum <= actual;
284+
285+
if ( ok )
286+
{
287+
logger.debug( String.format( "Coverage is above minimum [%s%% >= %s%%]: %s",
288+
actualFormatted, minimumFormatted, metric ) );
289+
}
290+
else
291+
{
292+
logger.error( String.format( "Coverage is below minimum [%s%% < %s%%]: %s",
293+
actualFormatted, minimumFormatted, metric ) );
294+
}
295+
296+
return ok;
297+
}
298+
}

0 commit comments

Comments
 (0)