Tag Archives: FitNesse

Tiny Types

Mark Needham’s post on micro types sparked an idea in my head that recently came to fruition.
I was pondering on the Narrative Fixture code, and the fact that, although most of the internals are sensibly typed objects, at the FitNesse layer, we do a lot of passing of strings.
The idea (at least, my interpretation) with Tiny Types is that the string obviously means something, and that we can probably classify what that meaning is (we have a sensibly named variable for it, after all) , and so why not convert it to that meaningful thing as soon as possible.
This has the nice effect of making some vague things (such as typing on collections) much more explicit.

As an example, in the Casting Director we have:

Map<String, ActorPlayingThe<?>> dressingRoom = new HashMap<String, ActorPlayingThe<?>>();

and, after a little bit of refactoring, we end up with:

Map<CharacterName, ActorPlayingThe<?>> dressingRoom = new HashMap<CharacterName, ActorPlayingThe<?>>();

Personally, I’m a fan of low ceremony, high essence languages, but while working in a high ceremony environment, we can leverage that ceremony to provide us with a nice summary of our thinking, ready for the next time we return to the code.

Showing FitNesse Test Results in Hudson

Have you tried to get your FitNesse reports into Hudson?

Although it’s simple to get an Ant task to run the tests, and fail the build, it would be nice to see the results in Hudson’s junit report.
Unfortunately FitNesse outputs it’s results in a format that Hudson doesn’t understand. But that’s OK, because it’s all XML.

I knocked together a really quick Proof of Concept xsl and ant script that allow you to run the FitNesse tests and convert the output to the Ant junit format that Hudson understands.

It’s a work in progress, but it should be enough to get you going. Watch this space.
I ran it against one suite and Hudson picked up the tests (and failure) ok.

This is the build.xml that I found on Naresh Jain’s blog about integrating FitNesse with CruiseControl, with the convert target added

<?xml version="1.0" encoding="UTF-8"?>
<project name="Acceptance_Tests-Common" default="test">
  <target name="smoke" description="Run fitnesse acceptance tests.">
    <property name="fitnesse.output.dir" value="build" />
    <property name="fitnesse.output.file" value="${fitnesse.output.dir}/fitnesse-test-results" />
    <property name="fitnesse.port" value="8765" />
    <path id="fitpath">
      <fileset dir=".">
        <include name="fit*.jar" />
        <include name="lib/fitnesse-20070619/fitnesse-20070619.jar" />
      </fileset>
    </path>
    <echo message="About to run fitnesse server" level="info" />
    <parallel>
      <daemons>
        <java classname="fitnesse.FitNesse" classpath="${toString:fitpath};${ant.home}/lib/xercesImpl.jar">
          <arg value="-p" />
          <arg value="${fitnesse.port}" />
          <arg value="-e" />
          <arg value="0" />
          <arg value="-d" />
          <arg value="content" />
          <arg value="-r" />
          <arg value="FitnesseRoot" />
        </java>
      </daemons>
      <sequential>
        <echo message="sleeping for 10 seconds to let FitNesse server start" level="info" />
        <sleep seconds="10" />
        <java classpathref="fitpath" classname="fitnesse.runner.TestRunner" fork="true" resultproperty="fit.test.failures">
          <arg value="-debug" />
          <arg value="-xml" />
          <arg value="${fitnesse.output.file}.xml" />
          <arg value="-html" />
          <arg value="${fitnesse.output.file}.html" />
          <arg value="localhost" />
          <arg value="${fitnesse.port}" />
          <arg value="UserStories.FooterStory" />
        </java>
        <replace file="${fitnesse.output.file}.html" token="<base href="http://localhost:${fitnesse.port}/"/>" />
        <echo message="Finished FIT tests: ${fit.test.failures} failures/exceptions" level="info" />
        <!--
	  <fail message="FIT test failures/exceptions: ${fit.test.failures}">
	    <condition>
	      <not>
	        <equals arg1="${fit.test.failures}" arg2="0" />
	      </not>
            </condition>
	  </fail>
	  -->
      </sequential>
    </parallel>
  </target>

  <target name="convert-fitnesse-results-to-junit">
    <xslt style="fitnesse2junit.xsl" in="build/fitnesse-test-results.xml" out="build/TEST-fitnesse.xml" />
  </target>

  <target name="test" depends="smoke, convert-fitnesse-results-to-junit" />
</project>

A slight update on the XSL. This one creates the correct nodes for exceptions and errors (although it appears to make no difference to Hudson)

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <xsl:element name="testsuite">
    <xsl:attribute name="tests">
      <xsl:value-of select="sum(testResults/finalCounts/*)" />
    </xsl:attribute>
    <xsl:attribute name="failures">
      <xsl:value-of select="testResults/finalCounts/wrong" />
    </xsl:attribute>
    <xsl:attribute name="disabled">
      <xsl:value-of select="testResults/finalCounts/ignores" />
    </xsl:attribute>
    <xsl:attribute name="errors">
      <xsl:value-of select="testResults/finalCounts/exceptions" />
    </xsl:attribute>
    <xsl:attribute name="name">AcceptanceTests</xsl:attribute>
  <xsl:for-each select="testResults/result">
    <xsl:element name="testcase">
      <xsl:attribute name="classname">
        <xsl:value-of select="/testResults/rootPath" />
      </xsl:attribute>
      <xsl:attribute name="name">
        <xsl:value-of select="relativePageName" />
      </xsl:attribute>
      <xsl:choose>
        <xsl:when test="counts/exceptions > 0">
          <xsl:element name="error">
            <xsl:attribute name="message">
              <xsl:value-of select="counts/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>