Skip to content
mikec-bullhorn edited this page Feb 20, 2014 · 5 revisions

Cobertura can be used either from the command line or via Ant tasks. You can even mix and match the command line and Ant tasks. This document describes how to use Cobertura via Ant tasks.

You must first tell Ant about the Cobertura Ant tasks using a taskdef statement. The best place to do this is near the top of your build.xml script, before any target statements.

<property name="cobertura.dir" value="C:/javastuff/cobertura" />

<path id="cobertura.classpath">
    <fileset dir="${cobertura.dir}">
        <include name="cobertura.jar" />
        <include name="lib/**/*.jar" />
    </fileset>
</path>

<taskdef classpathref="cobertura.classpath" resource="tasks.properties" />

Cobertura-Instrument Task

Parameter Required? Description Default Value
datafile No Specify the name of the file to use for storing the metadata about your classes. This is a single file containing serialized Java classes. It contains information about the names of classes in your project, their method names, line numbers, etc. It will be updated as your tests are run, and will be referenced by the Cobertura reporting command. "cobertura.ser" in the current directory
maxmemory No Specify the maximum amount of memory used by the JVM. This is not normally needed, but you may need to specify a larger value if you see out of memory exceptions while this ant task is running. For example, "1024M". This might be needed if you have a very large number of classes. The default value for your system
todir No Specify the output directory for the instrumented classes. Note: If you do not specify a todir attribute, be careful to make sure to delete any instrumented class files whenever you delete your cobertura.ser file. If no destination directory is specified, then the uninstrumented classes will be overwritten with their instrumented counterparts.

Possible to specify a forked JVM max memory size?

You must tell Cobertura which class files to instrument by passing in standard ant filesets.

You can also pass in jar files to be instrumented using standard ant filesets. Cobertura will extract each class from the jar and instrument it. If 'todir' was not specified then the original jar will be overwritten with an instrumented version. Otherwise a new jar will be written to the output directory.

You can tell Cobertura to ignore certain classes by passing in "ignore" regular expressions. The ignore pattern can be any valid perl 5 regular expression. This will ignore any calls to any method that matches the ignore regular expression. It will NOT skip over these classes during instrumention. To exclude classes from being instrumented, either exclude them from your fileset or use the alternative method below and specify an excludeClasses pattern.

Example:

<delete file="cobertura.ser" />

<cobertura-instrument todir="${instrumented.dir}">
    <ignore regex="org.apache.log4j.*" />
    <fileset dir="${classes.dir}">
        <include name="**/*.class" />
        <exclude name="**/*Test.class" />
    </fileset>
    <fileset dir="${guiclasses.dir}">
        <include name="**/*.class" />
        <exclude name="**/*Test.class" />
    </fileset>
    <fileset dir="${jars.dir}">
        <include name="my-simple-plugin.jar" />
    </fileset>
</cobertura-instrument>

Alternatively you can specify a classpath and a set of classes to include and exclude, and Cobertura will look through the classpath and only instrument the specified classes. When this method is used, Cobertura will instrument archives inside of archives. For example, if you have a war file which contains a jar file at WEB-INF/lib, Cobertura will extract the war, instrument the classes within the jar, then build a new war containing the instrumented jar.

Example:

<delete file="cobertura.ser" />

<cobertura-instrument todir="${instrumented.dir}">
	<includeclasses regex=".*" />
	<excludeclasses regex=".*\.Test.*" />

	<instrumentationClasspath>
		<path refid="test.classpath" />
		<pathelement location="${test.build}" />
	</instrumentationClasspath>
</cobertura-instrument>

There were two new arguments that were added to the cobertura-instrument target.

Ignore Trivial

Ignore trivial allows the ability to exclude constructors/methods that contain one line of code. Some examples include a call to a super constrctor only, getter/setter methods, etc. To include the ignore trivial argument add the following:

<cobertura-instrument ignoreTrivial="true" />

Ignore Method Annotation

Ignore Method Annotation allows the exclusion of certain methods from being instrumented based on an annotation. In order to get this to work, first an annotation must be created:

package foo.bar;

public @interface CoberturaIgnore{}

A simple one like this is good enough. Next we want to add this to each method we want excluded. Please note this does WILL NOT work at the class level:

WILL WORK:

public class Foo {
  @CoverageIgnore
  public void bar() {...}
}

WILL NOT WORK:

@CoverageIgnore
public class Foo {
  public void bar() {...}
}

Finally adding the annotation to the cobertura-instrument task:

<cobertura-instrument>
  <ignoreMethodAnnotation annotationName="foo.bar.CoverageIgnore"/>
</cobertura-instrument>

Please note that the package and the annotation name are both required in order for cobertura to properly exclude the method.

Adding auxClasspath

auxClasspath argument is designed to remove the ClassNotFoundException during instrumentation. See https://github.com/cobertura/cobertura/wiki/FAQ#classnotfoundexception-during-instrumentation for more information on this argument

<cobertura-instrument>
  <auxClasspath path="Test.jar" />
</cobertura-instrument>

Running Tests

Here's an example call to the JUnit ant task that has been modified to work with Cobertura. Important settings are highlighted in blue.

<junit fork="yes" dir="${basedir}" failureProperty="test.failed">
	<!--
		Specify the name of the coverage data file to use.
		The value specified below is the default.
	-->
	<sysproperty key="net.sourceforge.cobertura.datafile"
		file="${basedir}/cobertura.ser" />

	<!--
		Note the classpath order: instrumented classes are before the
		original (uninstrumented) classes.  This is important.
	-->
	<classpath location="${instrumented.dir}" />
	<classpath location="${classes.dir}" />

	<!--
		The instrumented classes reference classes used by the
		Cobertura runtime, so Cobertura and its dependencies
		must be on your classpath.
	-->
	<classpath refid="cobertura_classpath" />

	<formatter type="xml" />
	<test name="${testcase}" todir="${reports.xml.dir}" if="testcase" />
	<batchtest todir="${reports.xml.dir}" unless="testcase">
		<fileset dir="${src.dir}">
			<include name="**/*Test.java" />
		</fileset>
	</batchtest>
</junit>

The following 4 components are the most important to get cobertura code coverage to work

  • fork="yes"

It is important to set fork="true" or "yes" because of the way Cobertura works. It only flushes its changes to the coverage data file to disk when the JVM exits. If JUnit runs in the same JVM as ant, then the coverage data file will be updated AFTER ant exits, but you want to run cobertura-report BEFORE ant exits.

For this same reason, if you're using ant 1.6.2 or higher then you might want to set forkmode="once" This will cause only one JVM to be started for all your JUnit tests, and will reduce the overhead of Cobertura reading/writing the coverage data file each time a JVM starts/stops.

  • <sysproperty key="net.sourceforge.cobertura.datafile" file="${basedir}/cobertura.ser" />

This is a static variable that contains the location of the datafile. If the datafile moves, this lets the JVM know that the datafile has moved and is not in the current(or present) working directory.

  • <classpath location="${instrumented.dir}" />

Adding the instrumented classes before the actual classes guarantees that cobertura source code gets used first. This is required because we want to use the cobertura instrumented code instead of the regular compiled code, however we keep both versions just in case there's an issue with instrumentation.

  • <classpath refid="cobertura_classpath" />

Creating a reference id that contains just the cobertura.jar is important to guarantee that there is no NoClassDefFound exception with cobertura. When executing test units, the only dependency cobertura requires is the cobertura.jar file. All the other files are necessary for instrumentation, reporting and merging of tasks.

Cobertura-Report Task

Parameter Required? Description Default Value
format No The type of report you want to generate. html
datafile No Specify the name of the file containing metadata about your classes. "cobertura.ser" in the current directory
destdir Yes Specify the output directory for the report. No default value.
maxmemory No Specify the maximum amount of memory used by the JVM. This is not normally needed, but you may need to specify a larger value if you see out of memory exceptions while this ant task is running. This could happen when you have a very large number of classes. The default value for your system
srcdir Yes Specify the directory containing the source code of your project. This is used to calculate the cyclomatic code complexity of each class. The HTML reports are also made of annotated versions of each source file, showing which lines of code were exercised. No default value.
encoding No Specify the encoding used to read the source. See javadocs for java.nio.charset.Charset for more details. Since 1.9.1. The default encoding.

Alternately, you may specify source directories using nested filesets. This is required if you have more than one directory of source code.

Example:

<cobertura-report format="html" destdir="${coveragereport.dir}" srcdir="${src.dir}" />

Example with multiple source directories:

<cobertura-report format="html" destdir="${coveragereport.dir}" >
    <fileset dir="${src.dir}">
        <include name="**/*.java" />
        <exclude name="**/*Stub.java" />
    </fileset>
    <fileset dir="${guisrc.dir}">
        <include name="**/*.java" />
        <exclude name="**/*RB.java" />
    </fileset>
</cobertura-report>

Cobertura-Check Task

Parameter Required? Description Default Value
branchrate No Specify the minimum acceptable branch coverage rate needed by each class. This should be an integer value between 0 and 100. 0
datafile No Specify the name of the file containing metadata about your classes. "cobertura.ser" in the current directory
failureproperty No If haltonfailure is false and any of the specified checks fails, then Cobertura will set the given property to "true" None
haltonfailure No If this property is true and any of the specified checks fails, then Cobertura will cause the ant build to fail. True
linerate No Specify the minimum acceptable line coverage rate needed by each class. This should be an integer value between 0 and 100. 0
packagebranchrate No Specify the minimum acceptable average branch coverage rate needed by each package. This should be an integer value between 0 and 100. 0
packagelinerate No Specify the minimum acceptable average line coverage rate needed by each package. This should be an integer value between 0 and 100. 0
totalbranchrate No Specify the minimum acceptable average branch coverage rate needed by the project as a whole. This should be an integer value between 0 and 100. 0
totallinerate No Specify the minimum acceptable average line coverage rate needed by the project as a whole. This should be an integer value between 0 and 100. 0

If you do not specify branchrate, linerate, totalbranchrate or totallinerate, then Cobertura will use 50% for all of these values.

You can specify finer-grained thresholds for certain classes using regular expressions. See the example below.

Example:

<cobertura-check branchrate="30" totalbranchrate="60" totallinerate="80">
    <regex pattern="com.example.reallyimportant.*" branchrate="80" linerate="90"/>
    <regex pattern="com.example.boringcode.*" branchrate="40" linerate="30"/>
</cobertura-check>

Cobertura-Merge Task

Parameter Required? Description Default Value
datafile No Specify the name of the file containing metadata about your classes. This is the "destination" file into which the contents of the other data files will be merged. "cobertura.ser" in the current directory.
maxmemory No Specify the maximum amount of memory used by the JVM. This is not normally needed, but you may need to specify a larger value if you see out of memory exceptions while this ant task is running. This could happen when you have a very large number of classes. The default value for your system.

You must tell Cobertura which coverage data files to merge by passing in standard ant filesets.

Example:

<cobertura-merge>
    <fileset dir="${test.execution.dir}">
        <include name="server/cobertura.ser" />
        <include name="client/cobertura.ser" />
    </fileset>
</cobertura-merge>