How to Clover Ant

Clovering Ant is a little more complicated that clovering a regular Java project because Clover itself is running within Ant as a compiler adapter. We only want the Clovered Ant to be used for the test run. All other Ant operations needs to be done with a non-clovered Ant, or they’ll affect the results.

Luckily the standard build system for Ant works this way anyway. When Ant is built, a bootstrap version of Ant is built to actually do the full Ant build. We can use the bootstrap Ant as the non-clovered Ant to clover the main Ant build.

I have an Ant build file, clover.xml, which does everything for me. The steps are

  1. bootstrap Ant
  2. build -f clover.xml complete

In the second step, there are a few other targets we can use besides the "complete" target. These give different variations.

I’ll briefly explain each of the targets in the build.

  • The taskdefs define the ant-contrib and clover tasks. The ant-contrib foreach task is only used in the generation of historical data. This only has to be done once
  • setup – sets up the clover properties with the clover-setup task.
  • clover – This target does the work for a single clover run. The ant tasks clean up any old builds, build the code and build the test code. The clean and test code builds do not inherit properties preventing the clover build.compiler value from affecting these operations. The build operation on the other hand picks up the clover properties and references, so that the build.compiler property is set in the sub-build, thereby enabling Clover in the compilation. The current Ant installation is then removed. Before you use this build, your should obviously make sure it is OK to remove the current installation of Ant. Any optional libraries are copied to the install and the rest of Ant installed with the final Ant call. Once the clovered Ant is installed, it is used to run the Ant test suite, generating the clover database
  • core, all – these two targets are similar to the clover target. The differences are that these targets, clean out the clover database and also generate a clover history point at the end of the run. Additionally, the core target has a patternset so that it only clovers the Ant core, leaving out the optional tasks.
  • complete – sets the date for the history generation to the current date, does a core run, a full run and then generates the reports.
  • report – this target generates three Clover reports. It starts by setting up a common format to be used by all the reports and then generating the historical and current reports.
  • generate-history – this target uses the coreach task to generate a history point for a set of dates. The list includes a point for each month back to 2001.
  • genfordate – this does the generation of a single history point. It uses the date of the history point to checkout the version of Ant from CVS appropriate to the date and then uses the "core" and "all" targets for the actual test run.

If you are using the generate-history target you will not be able to use build.sh to do the build because CVS updates will continually change it. You will need to make a copy of the script prior to the build and use that copy instead.

It was pretty interesting to run this and watch a few years of Ant development come and go in a few hours. It’s also impressive that this same basic setup can work back to early 2001. It’s not perfect, of course, since some things (such as test.haltonfailure) only work on more recent builds.

When you are finished, you’ll want to do a final CVS update to get back to the current HEAD version.

That’s all there is to clovering Ant. The principles should be applicable to other projects, especially the generation of the historical reports.