2222
2323import org .apache .maven .plugin .AbstractMojo ;
2424import org .apache .maven .plugin .MojoFailureException ;
25+ import org .apache .maven .plugin .logging .Log ;
2526import org .apache .maven .plugins .annotations .Execute ;
2627import org .apache .maven .plugins .annotations .LifecyclePhase ;
2728import org .apache .maven .plugins .annotations .Mojo ;
2829import org .apache .maven .plugins .annotations .Parameter ;
2930import org .apache .maven .project .MavenProject ;
3031
3132import scala .Predef$ ;
33+ import scala .collection .JavaConversions ;
3234
3335import scoverage .Coverage ;
3436import 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