Skip to content

Commit 44ab980

Browse files
author
Albert Meltzer
committed
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 cc9d275 commit 44ab980

File tree

2 files changed

+115
-24
lines changed

2 files changed

+115
-24
lines changed

README.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,12 @@ Read [SBT SCoverage Plugin documentation](https://github.com/scoverage/sbt-scove
278278
<artifactId>scoverage-maven-plugin</artifactId>
279279
<version>${scoverage.plugin.version}</version>
280280
<configuration>
281-
<minimumCoverage>80</minimumCoverage>
281+
<minimumCoverage>95</minimumCoverage>
282+
<minimumBranchCoverageTotal>90</minimumBranchCoverageTotal>
283+
<minimumStmtCoveragePerPackage>90</minimumStmtCoveragePerPackage>
284+
<minimumBranchCoveragePerPackage>85</minimumBranchCoveragePerPackage>
285+
<minimumStmtoveragePerFile>85</minimumStmtoveragePerFile>
286+
<minimumBranchCoveragePerFile>80</minimumBranchCoveragePerFile>
282287
<failOnMinimumCoverage>true</failOnMinimumCoverage>
283288
</configuration>
284289
<executions>

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

+109-23
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@
2222

2323
import org.apache.maven.plugin.AbstractMojo;
2424
import org.apache.maven.plugin.MojoFailureException;
25+
import org.apache.maven.plugin.logging.Log;
2526
import org.apache.maven.plugins.annotations.Execute;
2627
import org.apache.maven.plugins.annotations.LifecyclePhase;
2728
import org.apache.maven.plugins.annotations.Mojo;
2829
import org.apache.maven.plugins.annotations.Parameter;
2930
import org.apache.maven.project.MavenProject;
3031

3132
import scala.Predef$;
33+
import scala.collection.JavaConversions;
3234

3335
import scoverage.Coverage;
3436
import scoverage.IOUtils;
@@ -68,7 +70,7 @@ public class SCoverageCheckMojo
6870
private File dataDirectory;
6971

7072
/**
71-
* Required minimum coverage.
73+
* Required minimum total statement coverage.
7274
* <br>
7375
* <br>
7476
* See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
@@ -79,6 +81,56 @@ public class SCoverageCheckMojo
7981
@Parameter( property = "scoverage.minimumCoverage", defaultValue = "0" )
8082
private Double minimumCoverage;
8183

84+
/**
85+
* Required minimum total branch coverage.
86+
* <br>
87+
* <br>
88+
* See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
89+
* <br>
90+
*/
91+
@Parameter( property = "scoverage.minimumCoverage.BranchTotal", defaultValue = "0" )
92+
private Double minimumCoverageBranchTotal;
93+
94+
/**
95+
* Required minimum per-package statement coverage.
96+
* <br>
97+
* <br>
98+
* See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
99+
* <br>
100+
*/
101+
@Parameter( property = "scoverage.minimumCoverage.StmtPerPackage", defaultValue = "0" )
102+
private Double minimumCoverageStmtPerPackage;
103+
104+
/**
105+
* Required minimum per-package branch coverage.
106+
* <br>
107+
* <br>
108+
* See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
109+
* <br>
110+
*/
111+
@Parameter( property = "scoverage.minimumCoverage.BranchPerPackage", defaultValue = "0" )
112+
private Double minimumCoverageBranchPerPackage;
113+
114+
/**
115+
* Required minimum per-file statement coverage.
116+
* <br>
117+
* <br>
118+
* See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
119+
* <br>
120+
*/
121+
@Parameter( property = "scoverage.minimumCoverage.StmtPerFile", defaultValue = "0" )
122+
private Double minimumCoverageStmtPerFile;
123+
124+
/**
125+
* Required minimum per-file branch coverage.
126+
* <br>
127+
* <br>
128+
* See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
129+
* <br>
130+
*/
131+
@Parameter( property = "scoverage.minimumCoverage.BranchPerFile", defaultValue = "0" )
132+
private Double minimumCoverageBranchPerFile;
133+
82134
/**
83135
* Fail the build if minimum coverage was not reached.
84136
* <br>
@@ -160,27 +212,23 @@ public void execute() throws MojoFailureException
160212
getLog().info( String.format( "Branch coverage....: %s%%", coverage.branchCoverageFormatted() ) );
161213
getLog().debug( String.format( "invokedBranchesCount:%d / branchCount:%d, invokedStatementCount:%d / statementCount:%d",
162214
invokedBranchesCount, branchCount, invokedStatementCount, statementCount ) );
163-
if ( minimumCoverage > 0.0 )
215+
216+
boolean ok = checkCoverage( getLog(), "Total", coverage,
217+
minimumCoverage, minimumCoverageBranchTotal );
218+
for ( scoverage.MeasuredPackage pkgCoverage : JavaConversions.asJavaIterable( coverage.packages() ) )
164219
{
165-
String minimumCoverageFormatted = scoverage.DoubleFormat.twoFractionDigits( minimumCoverage );
166-
if ( is100( minimumCoverage ) && is100( coverage.statementCoveragePercent() ) )
167-
{
168-
getLog().info( "100% Coverage !" );
169-
}
170-
else if ( coverage.statementCoveragePercent() < minimumCoverage )
171-
{
172-
getLog().error( String.format( "Coverage is below minimum [%s%% < %s%%]",
173-
coverage.statementCoverageFormatted(), minimumCoverageFormatted ) );
174-
if ( failOnMinimumCoverage )
175-
{
176-
throw new MojoFailureException( "Coverage minimum was not reached" );
177-
}
178-
}
179-
else
180-
{
181-
getLog().info( String.format( "Coverage is above minimum [%s%% >= %s%%]",
182-
coverage.statementCoverageFormatted(), minimumCoverageFormatted ) );
183-
}
220+
ok &= checkCoverage( getLog(), "Package:" + pkgCoverage.name(), pkgCoverage,
221+
minimumCoverageStmtPerPackage, minimumCoverageBranchPerPackage );
222+
}
223+
for ( scoverage.MeasuredFile fileCoverage : JavaConversions.asJavaIterable( coverage.files() ) )
224+
{
225+
ok &= checkCoverage( getLog(), "File:" + fileCoverage.filename(), fileCoverage,
226+
minimumCoverageStmtPerFile, minimumCoverageBranchPerFile );
227+
}
228+
229+
if ( !ok && failOnMinimumCoverage )
230+
{
231+
throw new MojoFailureException( "Coverage minimum was not reached" );
184232
}
185233

186234
long te = System.currentTimeMillis();
@@ -189,9 +237,47 @@ else if ( coverage.statementCoveragePercent() < minimumCoverage )
189237

190238
// Private utility methods
191239

192-
private boolean is100( Double d )
240+
private static boolean is100( Double d )
193241
{
194242
return Math.abs( 100 - d ) <= 0.00001d;
195243
}
196244

197-
}
245+
private static boolean checkCoverage( Log logger, String metric, scoverage.CoverageMetrics metrics,
246+
double minimumStmt, double minimimBranch )
247+
{
248+
return
249+
checkCoverage( logger, "Statement:" + metric, minimumStmt, metrics.statementCoveragePercent() ) &&
250+
checkCoverage( logger, "Branch:" + metric, minimimBranch, metrics.branchCoveragePercent() );
251+
}
252+
253+
private static boolean checkCoverage( Log logger, String metric, double minimum, double actual )
254+
{
255+
if ( minimum <= 0 )
256+
{
257+
return true;
258+
}
259+
260+
if ( is100( minimum ) && is100( actual ) )
261+
{
262+
logger.debug( String.format( "Coverage is 100%: %s!", metric ));
263+
return true;
264+
}
265+
266+
String minimumFormatted = scoverage.DoubleFormat.twoFractionDigits( minimum );
267+
String actualFormatted = scoverage.DoubleFormat.twoFractionDigits( actual );
268+
boolean ok = minimum <= actual;
269+
270+
if ( ok )
271+
{
272+
logger.debug( String.format( "Coverage is above minimum [%s%% >= %s%%]: %s",
273+
actualFormatted, minimumFormatted, metric ) );
274+
}
275+
else
276+
{
277+
logger.error (String.format( "Coverage is below minimum [%s%% < %s%%]: %s",
278+
actualFormatted, minimumFormatted, metric ) );
279+
}
280+
281+
return ok;
282+
}
283+
}

0 commit comments

Comments
 (0)