Mchr3k - EmmaCheck

Home

EmmaCheck is an ant task which enforces particular Java code coverage levels.

Download emmacheck-0.2.jar

The Problem

EMMA is the Java code coverage engine used by the popular EclEmma Eclipse plugin. With a few extra lines in your ANT build.xml file you can generate a code coverage report for your Java project.

But what then? Will you ever look at the coverage report in the future?

The Solution

Measuring code coverage is most useful if you can actually enforce a particular level of coverage. EmmaCheck automates the checking of an EMMA code coverage report.

There are two common use cases.

Overall Code Coverage

First you need to download emmacheck-0.2.jar and place it within your java project. Second, you need to add the following lines near the top of your build.xml file to tell ANT about the emmacheck task.

<taskdef name="emmacheck" classname="org.emmacheck.EmmaCheckTask"
                          classpath="./lib/ant/emmacheck-0.2.jar"/>

The following lines of XML will check that 100% of lines were covered.

<emmacheck coveragefile="reports/coverage/coverage.emma"
           metadatafile="reports/coverage/metadata.emma"
           outputfile="reports/coverage/requiredcoverage.out"
           overallcoverage="L100" />

The overallcoverage parameter accepts 4 formats.

  • 100 - 100% of lines were covered
  • L100 - 100% of lines were covered
  • M100 - 100% of methods were covered
  • B100 - 100% of basic blocks were covered

Source Level Code Coverage

Getting 100% overall code coverage can be really difficult. However, it is much easier to get 100% coverage of particular files and this can also be enforced by emmacheck.

The following lines of XML will check that the coverage set out in requiredcoverage.properties is met.

<emmacheck coveragefile="reports/coverage/coverage.emma"
           metadatafile="reports/coverage/metadata.emma"
           outputfile="reports/coverage/requiredcoverage.out"
           requiredcoverage="config/requiredcoverage.properties" />

requiredcoverage.properties should look something like this.

org.example.Source.java               = L100
org.example.subpackage.SubSource.java = B95

Complete Example

This section includes a complete example build.xml file showing how to do all of the following.

  • Compile your code
  • Instrument the compiled code
  • Compile your tests
  • Run your tests against the instrumented code
  • Generate an EMMA report
  • Run the EmmaCheck task to check the level of code coverage

Here is the ANT build.xml file.

<project name="Example" basedir="." default="help">

  <path id="emma.lib" >
    <pathelement location="./lib/ant/emma.jar" />
    <pathelement location="./lib/ant/emma_ant.jar" />
  </path>
  <path id="project.classpath" >
    <fileset dir="./lib" includes="*.jar" />
  </path>

  <taskdef resource="emma_ant.properties" classpathref="emma.lib" />
  <taskdef name="emmacheck" classname="org.emmacheck.EmmaCheckTask"
           classpath="./lib/ant/emmacheck-0.2.jar"/>

  <target name="help">
    <java classname="org.apache.tools.ant.Main">
      <arg value="-projecthelp" />
    </java>
  </target>

  <target name="clean" description="Clean built files">
    <delete dir="./build" />
    <delete dir="./reports" />
  </target>

  <target name="build" description="Build classes">

    <mkdir dir="./build" />
    <mkdir dir="./build/classes" />

    <!-- Compile project source code -->
    <javac classpathref="project.classpath"
           destdir="./build/classes"
           debug="true"
           source="1.6"
           target="1.6"
           includeAntRuntime="false">
      <src path="./src" />
    </javac>

  </target>

  <target name="test" description="Run UTs and generate code coverage report" depends="build">
    <property name="emma.enabled" value="true" />

    <mkdir dir="./reports" />
    <mkdir dir="./reports/test" />
    <mkdir dir="./reports/test/raw" />
    <mkdir dir="./reports/coverage" />
    <mkdir dir="./reports/coverage/metadata" />

    <mkdir dir="./build/test" />
    <mkdir dir="./build/classes_instr" />

    <!-- Compile test source code -->
    <javac destdir="./build/test" debug="true" source="1.6" target="1.6" includeAntRuntime="false">
      <src path="./testsrc"/>
      <classpath>
        <pathelement path="./build/classes" />
        <path refid="project.classpath" />
        <path refid="test.classpath" />
      </classpath>
    </javac>

    <!-- Copy base class files -->
    <copy todir="./build/classes_instr">
      <fileset dir="./build/classes" />
    </copy>

    <!-- Instrument class files -->
    <emma enabled="${emma.enabled}" >
      <instr instrpath="./build/classes_instr"
             metadatafile="./reports/coverage/metadata/metadata.emma"
             merge="true"
             mode="overwrite"
      />
    </emma>

    <!-- Run tests using the instrumented class files -->
    <junit printsummary="yes" haltonfailure="yes">
      <classpath>
        <pathelement location="./build/classes_instr"/>
        <pathelement location="./build/test"/>
        <path refid="emma.lib" />
        <path refid="project.classpath" />
      </classpath>
      <jvmarg value="-Demma.coverage.out.file=./reports/coverage/metadata/coverage.emma" />
      <jvmarg value="-Demma.coverage.out.merge=true" />

      <formatter type="xml"/>
      <formatter type="plain"/>

      <batchtest fork="yes" todir="./reports/test/raw">
      <fileset dir="./testsrc">
        <include name="**/*TestCase.java"/>
      </fileset>
      </batchtest>
    </junit>

    <!-- Generate a JUnit report -->
    <junitreport todir="./reports/test">
      <fileset dir="./reports/test/raw">
        <include name="TEST-*.xml"/>
      </fileset>
      <report format="frames" todir="./reports/test/"/>
    </junitreport>

    <!-- Generate EMMA reports -->
    <emma enabled="${emma.enabled}" >
      <report sourcepath="./src" >
        <fileset dir="./reports/coverage/metadata/" >
          <include name="*.emma" />
        </fileset>

        <txt outfile="./reports/coverage/coverage.txt" />
        <html outfile="./reports/coverage/coverage.html" depth="class"/>
      </report>
    </emma>

    <!-- Check the EMMA code coverage against requiredcoverage.properties -->
    <emmacheck coveragefile="./reports/coverage/metadata/coverage.emma"
               metadatafile="./reports/coverage/metadata/metadata.emma"
               requiredcoverage="./config/requiredcoverage.properties"
               output="./reports/coverage/requiredcoverage.out" />
  </target>  

</project>