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 ;
2930import org .apache .maven .plugins .annotations .Parameter ;
3031import org .apache .maven .project .MavenProject ;
3132
33+ import scala .collection .JavaConversions ;
3234import scala .collection .JavaConverters ;
3335
3436import scoverage .Coverage ;
@@ -69,7 +71,7 @@ public class SCoverageCheckMojo
6971 private File dataDirectory ;
7072
7173 /**
72- * Required minimum coverage.
74+ * Required minimum total statement coverage.
7375 * <br>
7476 * <br>
7577 * See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
@@ -80,6 +82,56 @@ public class SCoverageCheckMojo
8082 @ Parameter ( property = "scoverage.minimumCoverage" , defaultValue = "0" )
8183 private Double minimumCoverage ;
8284
85+ /**
86+ * Required minimum total branch coverage.
87+ * <br>
88+ * <br>
89+ * See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
90+ * <br>
91+ */
92+ @ Parameter ( property = "scoverage.minimumCoverageBranchTotal" , defaultValue = "0" )
93+ private Double minimumCoverageBranchTotal ;
94+
95+ /**
96+ * Required minimum per-package statement coverage.
97+ * <br>
98+ * <br>
99+ * See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
100+ * <br>
101+ */
102+ @ Parameter ( property = "scoverage.minimumCoverageStmtPerPackage" , defaultValue = "0" )
103+ private Double minimumCoverageStmtPerPackage ;
104+
105+ /**
106+ * Required minimum per-package branch coverage.
107+ * <br>
108+ * <br>
109+ * See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
110+ * <br>
111+ */
112+ @ Parameter ( property = "scoverage.minimumCoverageBranchPerPackage" , defaultValue = "0" )
113+ private Double minimumCoverageBranchPerPackage ;
114+
115+ /**
116+ * Required minimum per-file statement coverage.
117+ * <br>
118+ * <br>
119+ * See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
120+ * <br>
121+ */
122+ @ Parameter ( property = "scoverage.minimumCoverageStmtPerFile" , defaultValue = "0" )
123+ private Double minimumCoverageStmtPerFile ;
124+
125+ /**
126+ * Required minimum per-file branch coverage.
127+ * <br>
128+ * <br>
129+ * See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
130+ * <br>
131+ */
132+ @ Parameter ( property = "scoverage.minimumCoverageBranchPerFile" , defaultValue = "0" )
133+ private Double minimumCoverageBranchPerFile ;
134+
83135 /**
84136 * Fail the build if minimum coverage was not reached.
85137 * <br>
@@ -161,27 +213,23 @@ public void execute() throws MojoFailureException
161213 getLog ().info ( String .format ( "Branch coverage....: %s%%" , coverage .branchCoverageFormatted () ) );
162214 getLog ().debug ( String .format ( "invokedBranchesCount:%d / branchCount:%d, invokedStatementCount:%d / statementCount:%d" ,
163215 invokedBranchesCount , branchCount , invokedStatementCount , statementCount ) );
164- if ( minimumCoverage > 0.0 )
216+
217+ boolean ok = checkCoverage ( getLog (), "Total" , coverage ,
218+ minimumCoverage , minimumCoverageBranchTotal );
219+ for ( scoverage .MeasuredPackage pkgCoverage : JavaConversions .asJavaIterable ( coverage .packages () ) )
165220 {
166- String minimumCoverageFormatted = scoverage .DoubleFormat .twoFractionDigits ( minimumCoverage );
167- if ( is100 ( minimumCoverage ) && is100 ( coverage .statementCoveragePercent () ) )
168- {
169- getLog ().info ( "100% Coverage !" );
170- }
171- else if ( coverage .statementCoveragePercent () < minimumCoverage )
172- {
173- getLog ().error ( String .format ( "Coverage is below minimum [%s%% < %s%%]" ,
174- coverage .statementCoverageFormatted (), minimumCoverageFormatted ) );
175- if ( failOnMinimumCoverage )
176- {
177- throw new MojoFailureException ( "Coverage minimum was not reached" );
178- }
179- }
180- else
181- {
182- getLog ().info ( String .format ( "Coverage is above minimum [%s%% >= %s%%]" ,
183- coverage .statementCoverageFormatted (), minimumCoverageFormatted ) );
184- }
221+ ok &= checkCoverage ( getLog (), "Package:" + pkgCoverage .name (), pkgCoverage ,
222+ minimumCoverageStmtPerPackage , minimumCoverageBranchPerPackage );
223+ }
224+ for ( scoverage .MeasuredFile fileCoverage : JavaConversions .asJavaIterable ( coverage .files () ) )
225+ {
226+ ok &= checkCoverage ( getLog (), "File:" + fileCoverage .filename (), fileCoverage ,
227+ minimumCoverageStmtPerFile , minimumCoverageBranchPerFile );
228+ }
229+
230+ if ( !ok && failOnMinimumCoverage )
231+ {
232+ throw new MojoFailureException ( "Coverage minimum was not reached" );
185233 }
186234
187235 long te = System .currentTimeMillis ();
@@ -190,9 +238,47 @@ else if ( coverage.statementCoveragePercent() < minimumCoverage )
190238
191239 // Private utility methods
192240
193- private boolean is100 ( Double d )
241+ private static boolean is100 ( Double d )
194242 {
195243 return Math .abs ( 100 - d ) <= 0.00001d ;
196244 }
197245
198- }
246+ private static boolean checkCoverage ( Log logger , String metric , scoverage .CoverageMetrics metrics ,
247+ double minimumStmt , double minimimBranch )
248+ {
249+ return
250+ checkCoverage ( logger , "Statement:" + metric , minimumStmt , metrics .statementCoveragePercent () ) &&
251+ checkCoverage ( logger , "Branch:" + metric , minimimBranch , metrics .branchCoveragePercent () );
252+ }
253+
254+ private static boolean checkCoverage ( Log logger , String metric , double minimum , double actual )
255+ {
256+ if ( minimum <= 0 )
257+ {
258+ return true ;
259+ }
260+
261+ if ( is100 ( minimum ) && is100 ( actual ) )
262+ {
263+ logger .debug ( String .format ( "Coverage is 100%: %s!" , metric ));
264+ return true ;
265+ }
266+
267+ String minimumFormatted = scoverage .DoubleFormat .twoFractionDigits ( minimum );
268+ String actualFormatted = scoverage .DoubleFormat .twoFractionDigits ( actual );
269+ boolean ok = minimum <= actual ;
270+
271+ if ( ok )
272+ {
273+ logger .debug ( String .format ( "Coverage is above minimum [%s%% >= %s%%]: %s" ,
274+ actualFormatted , minimumFormatted , metric ) );
275+ }
276+ else
277+ {
278+ logger .error ( String .format ( "Coverage is below minimum [%s%% < %s%%]: %s" ,
279+ actualFormatted , minimumFormatted , metric ) );
280+ }
281+
282+ return ok ;
283+ }
284+ }
0 commit comments