Skip to content

Commit

Permalink
Coverage minima: add more fine-grained control
Browse files Browse the repository at this point in the history
Along with existing statement minimum, add branch minimum. Also, include
this pair of control at the package and file level.
  • Loading branch information
Albert Meltzer committed Feb 18, 2018
1 parent cc9d275 commit 44ab980
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 24 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,12 @@ Read [SBT SCoverage Plugin documentation](https://github.com/scoverage/sbt-scove
<artifactId>scoverage-maven-plugin</artifactId>
<version>${scoverage.plugin.version}</version>
<configuration>
<minimumCoverage>80</minimumCoverage>
<minimumCoverage>95</minimumCoverage>
<minimumBranchCoverageTotal>90</minimumBranchCoverageTotal>
<minimumStmtCoveragePerPackage>90</minimumStmtCoveragePerPackage>
<minimumBranchCoveragePerPackage>85</minimumBranchCoveragePerPackage>
<minimumStmtoveragePerFile>85</minimumStmtoveragePerFile>
<minimumBranchCoveragePerFile>80</minimumBranchCoveragePerFile>
<failOnMinimumCoverage>true</failOnMinimumCoverage>
</configuration>
<executions>
Expand Down
132 changes: 109 additions & 23 deletions src/main/java/org/scoverage/plugin/SCoverageCheckMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Execute;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;

import scala.Predef$;
import scala.collection.JavaConversions;

import scoverage.Coverage;
import scoverage.IOUtils;
Expand Down Expand Up @@ -68,7 +70,7 @@ public class SCoverageCheckMojo
private File dataDirectory;

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

/**
* Required minimum total branch coverage.
* <br>
* <br>
* See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
* <br>
*/
@Parameter( property = "scoverage.minimumCoverage.BranchTotal", defaultValue = "0" )
private Double minimumCoverageBranchTotal;

/**
* Required minimum per-package statement coverage.
* <br>
* <br>
* See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
* <br>
*/
@Parameter( property = "scoverage.minimumCoverage.StmtPerPackage", defaultValue = "0" )
private Double minimumCoverageStmtPerPackage;

/**
* Required minimum per-package branch coverage.
* <br>
* <br>
* See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
* <br>
*/
@Parameter( property = "scoverage.minimumCoverage.BranchPerPackage", defaultValue = "0" )
private Double minimumCoverageBranchPerPackage;

/**
* Required minimum per-file statement coverage.
* <br>
* <br>
* See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
* <br>
*/
@Parameter( property = "scoverage.minimumCoverage.StmtPerFile", defaultValue = "0" )
private Double minimumCoverageStmtPerFile;

/**
* Required minimum per-file branch coverage.
* <br>
* <br>
* See <a href="https://github.com/scoverage/sbt-scoverage#minimum-coverage">https://github.com/scoverage/sbt-scoverage#minimum-coverage</a> for additional documentation.
* <br>
*/
@Parameter( property = "scoverage.minimumCoverage.BranchPerFile", defaultValue = "0" )
private Double minimumCoverageBranchPerFile;

/**
* Fail the build if minimum coverage was not reached.
* <br>
Expand Down Expand Up @@ -160,27 +212,23 @@ public void execute() throws MojoFailureException
getLog().info( String.format( "Branch coverage....: %s%%", coverage.branchCoverageFormatted() ) );
getLog().debug( String.format( "invokedBranchesCount:%d / branchCount:%d, invokedStatementCount:%d / statementCount:%d",
invokedBranchesCount, branchCount, invokedStatementCount, statementCount ) );
if ( minimumCoverage > 0.0 )

boolean ok = checkCoverage( getLog(), "Total", coverage,
minimumCoverage, minimumCoverageBranchTotal );
for ( scoverage.MeasuredPackage pkgCoverage : JavaConversions.asJavaIterable( coverage.packages() ) )
{
String minimumCoverageFormatted = scoverage.DoubleFormat.twoFractionDigits( minimumCoverage );
if ( is100( minimumCoverage ) && is100( coverage.statementCoveragePercent() ) )
{
getLog().info( "100% Coverage !" );
}
else if ( coverage.statementCoveragePercent() < minimumCoverage )
{
getLog().error( String.format( "Coverage is below minimum [%s%% < %s%%]",
coverage.statementCoverageFormatted(), minimumCoverageFormatted ) );
if ( failOnMinimumCoverage )
{
throw new MojoFailureException( "Coverage minimum was not reached" );
}
}
else
{
getLog().info( String.format( "Coverage is above minimum [%s%% >= %s%%]",
coverage.statementCoverageFormatted(), minimumCoverageFormatted ) );
}
ok &= checkCoverage( getLog(), "Package:" + pkgCoverage.name(), pkgCoverage,
minimumCoverageStmtPerPackage, minimumCoverageBranchPerPackage );
}
for ( scoverage.MeasuredFile fileCoverage : JavaConversions.asJavaIterable( coverage.files() ) )
{
ok &= checkCoverage( getLog(), "File:" + fileCoverage.filename(), fileCoverage,
minimumCoverageStmtPerFile, minimumCoverageBranchPerFile );
}

if ( !ok && failOnMinimumCoverage )
{
throw new MojoFailureException( "Coverage minimum was not reached" );
}

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

// Private utility methods

private boolean is100( Double d )
private static boolean is100( Double d )
{
return Math.abs( 100 - d ) <= 0.00001d;
}

}
private static boolean checkCoverage( Log logger, String metric, scoverage.CoverageMetrics metrics,
double minimumStmt, double minimimBranch )
{
return
checkCoverage( logger, "Statement:" + metric, minimumStmt, metrics.statementCoveragePercent() ) &&
checkCoverage( logger, "Branch:" + metric, minimimBranch, metrics.branchCoveragePercent() );
}

private static boolean checkCoverage( Log logger, String metric, double minimum, double actual )
{
if ( minimum <= 0 )
{
return true;
}

if ( is100( minimum ) && is100( actual ) )
{
logger.debug( String.format( "Coverage is 100%: %s!", metric ));
return true;
}

String minimumFormatted = scoverage.DoubleFormat.twoFractionDigits( minimum );
String actualFormatted = scoverage.DoubleFormat.twoFractionDigits( actual );
boolean ok = minimum <= actual;

if ( ok )
{
logger.debug( String.format( "Coverage is above minimum [%s%% >= %s%%]: %s",
actualFormatted, minimumFormatted, metric ) );
}
else
{
logger.error (String.format( "Coverage is below minimum [%s%% < %s%%]: %s",
actualFormatted, minimumFormatted, metric ) );
}

return ok;
}
}

0 comments on commit 44ab980

Please sign in to comment.