Friday, December 18, 2009

Code Coverage with Maven 1.x / Cobertura

Many a times developers tend to compromise on testing every line and branch of code they crank. It becomes important that source files do not become cluttered with source lines that never gets invoked during the runtime.There goes a saying "Uncovered Code = Undiscovered Defects"

Of the three coverage tools I have used, JCoverage, Clover and Cobertura, I feel cobertura makes things simpler just for the fact it can be integrated with Ant and Maven without much of effort to generate coverage reports. In this post I shall explain how to generate a coverage report using Cobertura and Maven 1.x for a simple source file with three basic operations like add, subtract and delete.

1. Create a source file with the basic operations you need

public class Operator {
   
    public Integer add(int a, int b) {
        Integer sum = null;
        sum = a + b;
        return sum;
    }
   
    public Integer subtract(int a, int b) {
        Integer diff = null;
        diff = a - b;
        return diff;
    }
   
    public Double divide(double a, double b) {
        Double quotient = null;
        quotient = a / b;
        return quotient;
    }
}
 2. Export the source file you just created as a JAR(Java Archive) so that it can be used as a dependency while running the test class. Don't forget to place this archive into your maven repository. (For this example I have placed this jar under the artifactId sample-cobertura)

3. Create a test class to test the operations. I used JUnit 3.8.1 to create the test class as shown below

public class OperatorTest extends TestCase {

    private static Operator operator = null;
    public static Test suite() {
        final TestSuite suite = new TestSuite(OperatorTest.class);
        TestSetup wrapper = new TestSetup(suite) {
            protected void setUp() {
                oneTimeSetUp();
            }
        };

        return wrapper;
    }
   
    protected static void oneTimeSetUp() {
        operator = new Operator();
    }
   
    public void testAdd() {
        assertEquals(new Integer(5), operator.add(3, 2));
    }
   
    public void testSubtract() {
        assertEquals(new Integer(1), operator.subtract(3, 2));
    }
   
    public void testDivide() {
        assertEquals(new Double(2.0), operator.divide(6.0, 3.0));
    }
}
 4. Next would be to get the test class running with maven. For this example I used Maven 1.0.2 and installed maven-cobertura-plugin-1.4. For those familiar with Maven the site goal would also ensure running the tests in addition to generating the site reports. So I had only one goal in pom.xml to invoke the site command. Something like

    <goal name="maven-test-operator" prereqs="somegoal">
        <attainGoal name="site"/>
    </goal>
 5. Next step would be to create the project.xml without which you cannot run a maven project. In the project.xml specify the dependencies that your test class needs in order to run successfully. In this case junit.3.8.1 and the JAR created in Step 2 are the dependencies
    <dependencies>
 
        <dependency>
            <groupId>sample-cobertura</groupId>
            <artifactId>operator</artifactId>
            <type>jar</type>
            <jar>operator.jar</jar>
        </dependency>
       
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
        </dependency>
       
    </dependencies>
6. Now having defined the dependencies the next step would be to configure the <build> element in the project.xml. Don't forget to mention the source directory of the class for which you need the coverage reports. Your build element should look something like shown below
    <build>
        <sourceDirectory>${source.dir}/src/java</sourceDirectory>
        <unitTestSourceDirectory>src/test/java</unitTestSourceDirectory>
        <unitTest>
            <includes>
                <include>**/*Test.java</include>
            </includes>
            <resources>
                <resource>
                    <directory>${basedir}/src/test/java</directory>
                    <filtering>false</filtering>
                </resource>
            </resources>
        </unitTest>
    </build>
 7. The last step would be to add the <reports> tag in the project.xml

    <reports>
        <report>maven-junit-report-plugin</report>
        <report>maven-cobertura-plugin</report>
    </reports>
 8. We are ready to run the project. Navigate to your test root folder where you have the pom.xml and the project.xml and run the command maven maven-test-cobertura. Below shown the the folder structure I used and the pom.xml and project.xml were at the operator-test level
operator_test
├───bin
├───src
│   └───test
│       └───java
│           └───com
│               └───cobertura
│                   └───test

9. Sit back and relax, Maven will run the test class and generate the coverage report if everything goes on well. :) This is how the coverage report will look. As desired we have 100% coverage. The reports can be found inside the target directory that gets created


PS: This post assumes people to have a basic understanding of Maven. Those new to Maven might consider going through this link to get to know what Maven is all about. http://maven.apache.org/