Transforming FitNesse Results to Junit
I’ve been meaning to do this for a long time. Back when I was discussing how I got FitNesse to work on Hudson, I pointed out this page from Andrew Palmer. Since then, FitNesse has changed a little and I’ve had to adapt my script to work with those changes. So here is my XSL to transform FitNesse results XML into Junit results:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSLTransform">
<xsl:template match="/">
<xsl:element name="testsuite">
<xsl:attribute name="tests">
<xsl:value-of select="sum(suiteResults/finalCounts/\*)" />
</xsl:attribute>
<xsl:attribute name="failures">
<xsl:value-of select="suiteResults/finalCounts/wrong" />
</xsl:attribute>
<xsl:attribute name="disabled">
<xsl:value-of select="suiteResults/finalCounts/ignores" />
</xsl:attribute>
<xsl:attribute name="errors">
<xsl:value-of select="suiteResults/finalCountsexceptions" />
</xsl:attribute>
<xsl:attribute name="name"> <xsl:value-of select="suiteResults/rootPath" /> </xsl:attribute>
<xsl:for-each select="suiteResults/pageHistoryReference">
<xsl:element name="testcase">
<xsl:attribute name="classname">
<xsl:value-of select="/suiteResults/rootPath" />
</xsl:attribute>
<xsl:attribute name="name">
<xsl:value-of select="name" />
</xsl:attribute>
<xsl:attribute name="time">
<xsl:value-of select="runTimeInMillis div 1000" />
</xsl:attribute>
<xsl:choose>
<xsl:when test="counts/exceptions > 0">
<xsl:element name="error">
<xsl:attribute name="message">
<xsl:value-of select="count/exceptions" />
<xsl:text> exceptions thrown </xsl:text>
<xsl:if test="counts/wrong> 0">
<xsl:text> and </xsl:text>
<xsl:value-of select="counts/wrong" />
<xsl:text> assertions failed </xsl:text>
</xsl:if>
</xsl:attribute>
</xsl:element>
</xsl:when>
<xsl:when test="counts/wrong > 0">
<xsl:element name="failure">
<xsl:attribute name="message">
<xsl:value-of select="counts/wrong" />
<xsl:text> assertions failed </xsl:text>
</xsl:attribute>
</xsl:element>
</xsl:when>
</xsl:choose>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
o how do I use it?
First off I have the following ANT targets to run FitNesse and then capture the output:
<!--Run the tests first using the command line runner with text output. This lets us see the results as tests complete.-->
<java jar="javalib/fitnesse.jar" classpath="${toString:install.classpath}" fork="true" maxmemory="1024m">
<arg value="-c" />
<arg value="${fitnesseSuite}?suite&suiteFilter=${fitnesseSuiteFilter}&excludeSuiteFilter=${fitnesseExcludeSuiteFilter}&format=text" />
<arg value="-p"/>
<arg value="${fitnesse\_port}" />
</java>
<!--Then run the page history responder to get the latest run of fitnesse in xml format-->
<java jar="/javalib/fitnesse.jar" classpath="${toString:install.classpath}" fork="true" maxmemory="256m" output="${fitnesse.output.file}.temp" >
<arg value="-c" />
<arg value="${fitnesseSuite}?pageHistory&resultDate=latest&format=xml" />
<arg value="-p"/>
<arg value="${fitnesse\_port}" />
</java>
<!--Trim off the text that FitNesse sends before and after the XML-->
<exec executable="${env.RPFITDIR}/tools/XMLTrim.exe" output="${fitnesse.output.file}.xml">
<arg value="${fitnesse.output.file}.temp"/>
</exec>
The latest result will be written out to a temporary file, but won’t be true XML as there are http headers and traling characters around the XML. XMLTrim.exe is a little executable that can trim off the http headers in front of the XML results temporary file. I can’t share it right now, but will post something cross-platform in the future.
I have the following ANT target to transform the XML to the format we want.
<target name="convert-fitnesse-results-to-junit">
<xslt style="src/xsl/fitnesse2junit.xsl" in="${fitnesse.output.file}.xml" out="TEST-${fitnesse.output.file}.xml" >
</xslt>
</target>
Then I configure Hudson to use the results I generated, and we’re all set.