GroboUtils

About GroboUtils

Sourceforge
Project

For Developers

GroboCodeCoverage version 1.1.0

Integrating GroboCoverage With Complex Build Environments

Author:Matt Albrecht

Overview

This document attempts to describe what changes to the build file need to happen before you can get code-coverage reports with GroboCoverage.

The document will follow the generation of coverage numbers for an EJB site that uses Cactus to execute its JUnit tests. For simplicity, this will modify the sample application that comes packaged with Cactus (version 1.5, J2EE 1.2).

You can see the original version here, and the coverage-enabled version here.

Setup

You can download the Cactus package from the Jakarta binaries page. The sample application is located in the jakarta-cactus-12-1.5/samples/servlet directory.

You need to first copy the GroboCoverage libraries (GroboCodeCoverage-1.1.0-ant.jar and GroboCodeCoverage-1.1.0-runtime.jar) into the jakarta-cactus-12-1.5/lib directory so that our modified build file can reference it.

The build file will need more target directories:

  <property name="target.classes.coverage.dir"
      location="${target.classes.dir}/coverage"/>
  <property name="target.coverage.dir"
      location="${target.dir}/coverage"/>
  <property name="target.coveragereports.dir"
      location="${target.dir}/coverage-reports"/>
We also need to add a reference to the GroboCoverage runtime library:
  <property name="grobocoverage.jar"
      location="../../lib/GroboCodeCoverage-1.1.0-runtime.jar"/>
Then, right after the Cactus taskdef, we'll define the additional coverage tasks:
  <taskdef resource="ant-grobocoverage.properties"
        classpath="../../lib/GroboCodeCoverage-1.1.0-ant.jar" />

We also need a new target for post-compiling the Java class files:

  <!-- Instruments the java sources -->
  <target name="postcompile.java" depends="compile.java">
    
    <mkdir dir="${target.classes.coverage.dir}"/>
    <grobo-instrument logdir="${target.coverage.dir}"
        destdir="${target.classes.coverage.dir}"
        logger="fast">
      <fileset dir="${target.classes.java.dir}" />
      <measure type="linecount" />
    </grobo-instrument>
  </target>
which requires the "compile" target to change:
  <target name="compile" depends="compile.java, compile.cactus, postcompile.java"
      description="Compile the sources"/>
and the "test.prepare" target to also change its dependencies:
  <target name="test.prepare" 
      depends="war, compile.cactus, postcompile.java, test.prepare.logging">

Let's go ahead and add in the report generation steps after the <junitreport> tasks have run:

    <grobo-report logdir="${target.coverage.dir}">
      <source destdir="${target.coveragereports.dir}" removeempty="true"
          srcdir="${src.dir}" title="Sample Cactus Coverage Report" />
    </grobo-report>
This puts the source-linked report into the "target/coverage-reports" directory. This means that the report directory must already exist. So, at the end of the "test.prepare" target, add the lines:
    <!-- Prepare the directories for the coverage reports -->
    <mkdir dir="${target.coveragereports.dir}"/>
which will keep an I/O exception from being thrown during the report generation phase.

Augmenting The War File

So far, the changes to the build file have post-compiled the Java class files and generated a report.

The hard part still remains: alter the deployed war file so that it uses the post-compiled class files before it uses the Java class files.

Fortunately, this example "cactifies" the war file, so that the unit tests use a different war file than the distributable one.

Also, GroboCoverage provides a task that helps modify existing zip files. Add this immediately after the <cactifywar> task runs:

    
    <grobo-rezip>
        <alterWar src="${target.dir}/${project.name.file}-cactified.war"
            dest="${target.dir}/${project.name.file}-cactified-covered.war">
          <classes dir="${target.classes.coverage.dir}" />
          <lib file="${grobocoverage.jar}" />
        </alterWar>
    </grobo-rezip>
In this case, all we're modifying is the WAR file itself; a judicious use of a <zip> task could have accomplished the same thing. However, if instead of a WAR file, it used an EAR file, we'd have to unzip the EAR, alter the WAR, and rezip the EAR. Not too much fun.

Or, we could have put these classes and lib files into the <cactifywar> task. However, the rezip task was used for the sake of showing how to integrate GroboCoverage into complex sites, not just Cactus sites.

Then, we need to modify the <cactus> task. First, we replace the referenced war file:

    <cactus warfile="${target.dir}/${project.name.file}-cactified-coverage.war"
then alter the classpath so that it uses the post-compiled classes before the originals, and includes the GroboCoverage library file:
      <classpath>
        <path refid="project.classpath"/>
        <pathelement location="${httpunit.jar}"/>
        <pathelement location="${nekohtml.jar}"/>
        <pathelement location="${target.classes.coverage.dir}"/>
        <pathelement location="${target.classes.java.dir}"/>
        <pathelement location="${target.classes.cactus.dir}"/>
        <pathelement location="${log4j.jar}"/>
        <pathelement location="${grobocoverage.dir}"/>
      </classpath>
(yes, I chopped out that clover.jar reference; yuck!)

What We Learned

What did we learn from this lesson? If you attempt to gather code-coverage numbers from a deployed process, you need to make another deployable file using the post-compiled classes, rather than the originals. Also, to ensure that the client-side part of the tests have coverage numbers gathered, the same classpath steps must be taken as usual.




SourceForge Logo
This space graciously provided by the SourceForge project
Copyright © 2002-2004 GroboUtils Project.
All rights reserved.