Automated build systems (like NAnt or Ant) are excellent mechanisms with which to incorporate quality gates. An obvious quality gate is a successful test run (i.e. did all developer tests pass?); however, with the incorporation of software inspectors, you can introduce additional quality gates that verify specific code metrics or even combinations of metrics. Some software inspectors, in fact, already have built in mechanisms to cause build failures if specific thresholds are exceed, like Cobertura, which has a cobertura-check task that checks specific coverage values.

If a particular tool doesn’t provide an automatic failure hook, you can easily build one– in fact, combining Groovy’s expressive scripting power with Ant makes this process quite easy. For example, you can audit a JavaNCSS (a software inspector that reports code size and complexity) report and fail a build if the maximum complexity (which is reported for individual methods) is exceeded.

Imagine that as an organization, your team has set a goal that no method will have a cyclomatic complexity greater than 15. If for some reason, a method’s ccn (cyclomatic complexity number) is found to exceed 15, then a quality gate is tripped and a build is failed. This process is actually quite easy to script via Groovy in an Ant task. A number of things need to be in place for this to work:

  • A threshold value needs to be defined, preferably via an Ant property
  • JavaNCSS needs to be run as a prerequisite as the threshold task will parse the resulting XML report

If the defined threshold value is exceeded, then Ant’s fail task will be invoked. Watch how easy this is with Groovy:

<property name="maxccn" value="15" />

<target name="threshold-check" depends="groovy-init,javancss">
 <groovy classpathref="build.classpath">
  def fullpath = "${properties.basedir}/${properties.defaulttargetdir}"
  def jncssPath = "${fullpath}/javancss_metrics.xml"
  def jdoc = new XmlSlurper().parse(jncssPath)
  int maxccn = 0
  if(jdoc != null){
   jdoc.functions.function.each{ mthd ->
    int ccn = Integer.parseInt(mthd.ccn.text())
    if (ccn > maxccn){
     maxccn = ccn
    }
   }
  }
  if(maxccn > Integer.parseInt(properties.maxccn)){
    ant.fail(message:
      "Maximum CCN for a method was exceeded, value was ${maxccn}")
  }
 </groovy>
</target>

Running this task against a code base containing a method with a ccn greater than 15 will yield the following result:

$ ./run-ant.bat -Dnoget=true threshold-check
Buildfile: build.xml

init:
get-deps:
groovy-init:
javancss-init:
javancss:
 [javancss] Generating report

threshold-check:

BUILD FAILED
: Maximum CCN for a method was exceeded, value was 16

Total time: 3 seconds

This example, while useful, can be enhanced by comparing coverage as well as complexity– for instance, if the coverage dropped and complexity increased, this would be a far more adequate quality gate.

Software builds are excellent mechanisms to introduce automated quality gates– and as I’ve shown you, they’re easy to implement. As your build process matures, just remember to think through these quality gates so as to avoid false negatives. Simply failing a build because of a specific metric’s value has tripped a threshold could be dangerous. In the example above, if a method’s ccn value did exceed 15, one could argue that if that method also had high coverage, then some degree of risk has been avoided.