1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
<?xml version="1.0" encoding="ISO-8859-1"?>
<document>
<head>
<name>Integrating GroboCoverage With Complex Build Environments</name>
<doc-version>$Date: 2004/04/17 08:24:40 $</doc-version>
<author>Matt Albrecht</author>
</head>
<body>
<section>Overview</section>
<p>
This document attempts to describe what changes to the build file need
to happen before you can get code-coverage reports with GroboCoverage.
</p>
<p>
The document will follow the generation of coverage numbers for an EJB
site that uses <a href="http://jakarta.apache.org/cactus/index.html">Cactus</a>
to execute its JUnit tests. For simplicity, this will modify the sample
application that comes packaged with Cactus (version 1.5, J2EE 1.2).
</p>
<p>
You can see the original version <a href="cactus-sample-build.xml.txt">here</a>,
and the coverage-enabled version
<a href="cactus-sample-build-coverage.xml.txt">here</a>.
</p>
<section>Setup</section>
<p>
You can download the Cactus package from
<a href="http://jakarta.apache.org/site/binindex.cgi">the Jakarta binaries
page</a>. The sample application is located in the
<code>jakarta-cactus-12-1.5/samples/servlet</code> directory.
</p>
<p>
You need to first copy the GroboCoverage libraries
(GroboCodeCoverage-1.1.0-ant.jar and GroboCodeCoverage-1.1.0-runtime.jar)
into the <code>jakarta-cactus-12-1.5/lib</code> directory so that our
modified build file can reference it.
</p>
<p>
The build file will need more target directories:
<pre>
<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"/>
</pre>
We also need to add a reference to the GroboCoverage runtime library:
<pre>
<property name="grobocoverage.jar"
location="../../lib/GroboCodeCoverage-1.1.0-runtime.jar"/>
</pre>
Then, right after the Cactus taskdef, we'll define the additional coverage
tasks:
<pre>
<taskdef resource="ant-grobocoverage.properties"
classpath="../../lib/GroboCodeCoverage-1.1.0-ant.jar" />
</pre>
</p>
<p>
We also need a new target for post-compiling the Java class files:
<pre>
<!-- 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>
</pre>
which requires the "compile" target to change:
<pre>
<target name="compile" depends="compile.java, compile.cactus, postcompile.java"
description="Compile the sources"/>
</pre>
and the "test.prepare" target to also change its dependencies:
<pre>
<target name="test.prepare"
depends="war, compile.cactus, postcompile.java, test.prepare.logging">
</pre>
</p>
<p>
Let's go ahead and add in the report generation steps after the
<junitreport> tasks have run:
<pre>
<grobo-report logdir="${target.coverage.dir}">
<source destdir="${target.coveragereports.dir}" removeempty="true"
srcdir="${src.dir}" title="Sample Cactus Coverage Report" />
</grobo-report>
</pre>
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:
<pre>
<!-- Prepare the directories for the coverage reports -->
<mkdir dir="${target.coveragereports.dir}"/>
</pre>
which will keep an I/O exception from being thrown during the report
generation phase.
</p>
<section>Augmenting The War File</section>
<p>
So far, the changes to the build file have post-compiled the Java class
files and generated a report.
</p>
<p>
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.
</p>
<p>
Fortunately, this example "cactifies" the war file, so that the unit tests
use a different war file than the distributable one.
</p>
<p>
Also, GroboCoverage provides a task that helps modify existing zip files.
Add this immediately after the <code><cactifywar></code> task runs:
<pre>
<!-- +++ Create the code-coverage-enabled WAR file -->
<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>
</pre>
In this case, all we're modifying is the WAR file itself; a judicious use
of a <code><zip></code> 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.
</p>
<p>
Or, we could have put these classes and lib files into the
<code><cactifywar></code> task. However, the rezip task was used
for the sake of showing how to integrate GroboCoverage into complex sites,
not just Cactus sites.
</p>
<p>
Then, we need to modify the <code><cactus></code> task. First, we replace the
referenced war file:
<pre>
<cactus warfile="${target.dir}/${project.name.file}-cactified-coverage.war"
</pre>
then alter the classpath so that it uses the post-compiled classes before the
originals, and includes the GroboCoverage library file:
<pre>
<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>
</pre>
(yes, I chopped out that clover.jar reference; yuck!)
</p>
<section>What We Learned</section>
<p>
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.
</p>
</body>
</document>
|