2323
2424import org .apache .maven .plugin .AbstractMojo ;
2525import org .apache .maven .plugin .MojoFailureException ;
26+ import org .apache .maven .plugin .logging .Log ;
2627import org .apache .maven .plugins .annotations .Execute ;
2728import org .apache .maven .plugins .annotations .LifecyclePhase ;
2829import org .apache .maven .plugins .annotations .Mojo ;
3334import scala .jdk .javaapi .CollectionConverters ;
3435
3536import scoverage .domain .Coverage ;
37+ import scoverage .domain .CoverageMetrics ;
38+ import scoverage .domain .DoubleFormat ;
39+ import scoverage .domain .MeasuredFile ;
40+ import scoverage .domain .MeasuredPackage ;
3641import scoverage .reporter .IOUtils ;
3742import 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