@@ -28,6 +28,11 @@ object ScoverageSbtPlugin extends AutoPlugin {
2828 coverageExcludedPackages := " " ,
2929 coverageExcludedFiles := " " ,
3030 coverageMinimum := 0 , // default is no minimum
31+ coverageMinimumBranchTotal := 0 ,
32+ coverageMinimumStmtPerPackage := 0 ,
33+ coverageMinimumBranchPerPackage := 0 ,
34+ coverageMinimumStmtPerFile := 0 ,
35+ coverageMinimumBranchPerFile := 0 ,
3136 coverageFailOnMinimum := false ,
3237 coverageHighlighting := true ,
3338 coverageOutputXML := true ,
@@ -123,7 +128,7 @@ object ScoverageSbtPlugin extends AutoPlugin {
123128 sourceEncoding((scalacOptions in (Compile )).value),
124129 log)
125130
126- checkCoverage(cov, log, coverageMinimum .value, coverageFailOnMinimum.value)
131+ checkCoverage(cov, log, coverageMinima .value, coverageFailOnMinimum.value)
127132 case None => log.warn(" No coverage data, skipping reports" )
128133 }
129134 }
@@ -150,7 +155,7 @@ object ScoverageSbtPlugin extends AutoPlugin {
150155 val cfmt = cov.statementCoverageFormatted
151156 log.info(s " Aggregation complete. Coverage was [ $cfmt] " )
152157
153- checkCoverage(cov, log, coverageMinimum .value, coverageFailOnMinimum.value)
158+ checkCoverage(cov, log, coverageMinima .value, coverageFailOnMinimum.value)
154159 case None =>
155160 log.info(" No subproject data to aggregate, skipping reports" )
156161 }
@@ -244,28 +249,51 @@ object ScoverageSbtPlugin extends AutoPlugin {
244249
245250 private def checkCoverage (coverage : Coverage ,
246251 log : Logger ,
247- min : Double ,
252+ min : CoverageMinima ,
248253 failOnMin : Boolean ): Unit = {
254+ val ok : Boolean = checkCoverage(coverage, " Total" , log, min.total) &&
255+ coverage.packages.forall(x => checkCoverage(x, s " Package: ${x.name}" , log, min.perPackage)) &&
256+ coverage.files.forall(x => checkCoverage(x, s " File: ${x.filename}" , log, min.perFile))
257+
258+ if (! ok && failOnMin)
259+ throw new RuntimeException (" Coverage minimum was not reached" )
260+
261+ log.info(s " All done. Coverage was [ ${coverage.statementCoverageFormatted}%] " )
262+ }
249263
250- val cper = coverage.statementCoveragePercent
251- val cfmt = coverage.statementCoverageFormatted
264+ private def checkCoverage (metrics : CoverageMetrics ,
265+ metric : String ,
266+ log : Logger ,
267+ min : CoverageMinimum ): Boolean = {
268+ checkCoverage(s " Branch: $metric" , log, min.branch, metrics.branchCoveragePercent) &&
269+ checkCoverage(s " Stmt: $metric" , log, min.statement, metrics.statementCoveragePercent)
270+ }
252271
272+ private def checkCoverage (metric : String ,
273+ log : Logger ,
274+ min : Double ,
275+ cper : Double ): Boolean = {
253276 // check for default minimum
254- if (min > 0 ) {
277+ if (min <= 0 ) {
278+ true
279+ } else {
255280 def is100 (d : Double ) = Math .abs(100 - d) <= 0.00001
256281
257282 if (is100(min) && is100(cper)) {
258- log.info(s " 100% Coverage ! " )
259- } else if (min > cper) {
260- log.error(s " Coverage is below minimum [ $cfmt% < $min%] " )
261- if (failOnMin)
262- throw new RuntimeException (" Coverage minimum was not reached" )
283+ log.info(s " 100% Coverage: $metric" )
284+ true
263285 } else {
264- log.info(s " Coverage is above minimum [ $cfmt% > $min%] " )
286+ val ok : Boolean = min <= cper
287+ val minfmt = scoverage.DoubleFormat .twoFractionDigits(min)
288+ val cfmt = scoverage.DoubleFormat .twoFractionDigits(cper)
289+ if (ok) {
290+ log.info(s " Coverage is above minimum [ $cfmt% > $minfmt%]: $metric" )
291+ } else {
292+ log.error(s " Coverage is below minimum [ $cfmt% < $minfmt%]: $metric" )
293+ }
294+ ok
265295 }
266296 }
267-
268- log.info(s " All done. Coverage was [ $cfmt%] " )
269297 }
270298
271299 private def sourceEncoding (scalacOptions : Seq [String ]): Option [String ] = {
0 commit comments