◆ Problem
You are running JUnit with Ant and you need to customize the reports produced by the <junitreport> task.
◆ Background
If the two types of HTML reports that can be produced by Ant out of the box are not to your liking, you can define your own custom HTML output by customizing the existing XSL templates or by writing new ones from scratch.
Perhaps, instead of HTML output, you need a custom XML report format to facilitate importing test results into a test management system or a publishing engine (such as a PDF generator expecting a particular XML format). In these cases, you need a way to tell Ant to transform its default XML output into another XML format.
◆ Recipe
First, output test results in XML using the <formatter type="xml"> (see recipe 7.3,
“Getting plain text results with Ant”). Next, merge the results with the <junit- report> task. This creates one large XML results document. You have two main options for transforming this document using XSL stylesheets:
■ Customize one of the <junitreport>XSL stylesheets that comes with Ant.
■ Make <junitreport> use a custom XSL stylesheet of your own.
Customizing one of the existing XSL sheets is useful only if you want to mildly cus- tomize the format that Ant provides by default, such as embedding an image or changing the background color or fonts. This is because of some quirks and limi- tations of the <report> element (see the Discussion section for details).
For transforming XML formatted JUnit test results into HTML reports, Ant (since at least Ant 1.3) provides two XSL stylesheets in $ANT_HOME/etc: junit- frames.xsl and junit-noframes.xsl. Make a copy of either one for customiza- tion and keep your modified copy in a directory in your project. Then use your modified stylesheet to override the built-in default of the same name (either junit-frames.xsl or junit-noframes.xsl) by using the styledir attribute of the
<report> element.
206 CHAPTER 7
Reporting JUnit results
A simple but effective change to one of these stylesheets is to skip outputting into the HTML the listings of Java system property names and values recorded dur- ing the execution of each JUnit test. These properties listings are seldom useful, and they add many kilobytes of additional report file content, which can be an issue if trim, lightweight HTML reports are desired. Just comment out or delete the following elements (meaning everything between and including the opening and closing of the following named elements in the XSL) in junit-noframes.xsl (line numbers correspond to the line numbers in the actual junit-noframes.xsl file shipped with Ant 1.6.0):
1 Both <script> elements (lines 123–158)
2 The <div class="Properties"> element (lines 271–276)
3 The <xsl:template match="properties"> element (lines 334–340) Then you can point Ant to your modified stylesheet’s directory location (repre- sented by the property variable modified.xsl.dir below) in a target utilizing the
<junitreport> task and <report> element as shown in listing 7.5.
<target name="junit-custom-report"
description="=> generate XML and custom HTML reports">
<junitreport todir="${junit.reports.dir}/xml">
<fileset dir="${junit.reports.dir}/xml">
<include name="TEST-*.xml"/>
</fileset>
<report format="noframes" styledir="${modified.xsl.dir}"/>
</junitreport>
</target>
For more extreme transformations, we recommend using the <style>/<xslt>
task (this task has two names, which can be used interchangeably in Ant scripts, but we prefer <style>) as you normally would, using the merged XML file output by the <junitreport> task as the input file to the transformation.
To use the <style> task with Ant’s JUnit reporting, assume you have an XSL custom stylesheet written to transform <junitreport> XML results into another form of XML. Call it custom-junitreport.xsl. First, we usually want to merge together the individual XML results files output by the <batchtest>XML format- ter during a test run. The <junitreport> task can merge all those files, and do nothing else, if you just leave out the <report> element, as shown in listing 7.6:
Listing 7.5 Ant script snippet using <report> element with custom stylesheet
207 Customizing <junit> XML
reports with XSLT
<target name="junit-report"
description="=> generate JUnit merged XML report">
<junitreport todir="${junit.reports.dir}/xml">
<fileset dir="${junit.reports.dir}/xml">
<include name="TEST-*.xml"/>
</fileset>
</junitreport>
</target>
In the target shown in listing 7.6, the <junitreport> task merges together all the files matching the name pattern TEST-*.xml (which is the default output file nam- ing pattern of the XML formatter) in the ${junit.reports.dir}. By default, the resulting merged XML file is named TESTS-TestSuites.xml. The file TESTS-Test- Suites.xml is then passed as input to the <style> task, where your custom stylesheet guides the transformation, as shown in listing 7.7:
<target name="transform" description="=> create custom JUnit report">
<style in="${junit.reports.dir}/xml/TESTS-TestSuites.xml" B
out="TESTS-TestSuites.html"
extension=".html"
style="custom-junitreport.xsl"/> C
</target>
Test results to transform—The in attribute specifies the XML-based test results file to transform into a report. This file is a merged version of all the individual test suite result files.
XSL stylesheet for transformation—The style attribute specifies your custom XSL stylesheet for transforming the XML-based test results. The stylesheet could trans- form XML into HTML, a PDF, plain text or any other format. In our example, the target is an HTML report.
◆ Discussion
When using the <junitreport> task with a custom stylesheet, you must place the custom stylesheet in the directory specified by the styledir attribute of the
<report> element. You must name the stylesheet either junit-frames.xsl or junit-noframes.xsl. This is a quirk (arguably a defect) in the <report> element, which should be fixed so that it can take any file name for a stylesheet rather than demanding one of the two predefined file names to exist in a directory.
Listing 7.6 Ant script snippet using <junitreport> task to merge XML result files into one
Listing 7.7 Ant script snippet using <style> task just to transform XML results
B
C
208 CHAPTER 7
Reporting JUnit results
Another quirk is that the format attribute depends on the values frames or noframes (note that the default is frames, if format is left unspecified) even for custom stylesheets. Outside the context of HTML, specifying frames or noframes doesn’t make much sense. What if your stylesheet outputs XML or PDF? A work- around is to always name your custom XSL sheet as junit-frames.xsl and leave format unspecified. Because the format attribute defaults to frames, you can leverage that fact and tolerate not having descriptive filenames. Of course, if you have multiple custom stylesheets, separate them by descriptive directory names.
Also note that the frames-based report includes test output captured from the System.out stream, whereas the noframes report does not.
It seems that the advantage of the <junitreport> task for this set of problems is primarily in its XML-merging capabilities. Once the XML results files have been merged into a single large XML file, it would seem to be as easy, if not easier, to use a custom XSL sheet with the regular Ant <style> task as it would be to config- ure the <report> element to use a custom stylesheet.
So the answer is probably this: if you need minor tweaks to the format, use the
<report> task with one of the existing stylesheets and customize it. But if you need major changes to the output format, such as transforming the output to another XML structure, then use the <junitreport> task to merge the results into one file, and then use the <style> task to transform it with your custom stylesheet. The lat- ter option gives you all the features and options of the <style> task without the quirky limitations of the <report> task (which requires Xalan 2 and doesn’t sup- port nearly as many options as style/xslt).3
◆ Related
■ 7.4—Reporting results in HTML with Ant’s <junitreport> task