Kerry Buckley

What’s the simplest thing that could possibly go wrong?

An alternative approach to creating specs from JUnit tests

5 comments

I’m a convert to Behavior-Driven Development, or BDD, as championed by people like Dan North and Dave Astels. As a first step, I wanted to be able to generate a report from an existing collection of JUnit tests which read more like a set of specs (this would be in addition to the normal success/fail/error report), which would in turn be an encouragement to think in terms of behaviour specification when writing tests for new functionality.

To begin with, TestDox looked like just the job. Unfortunately, when I tried it I came across a few things that weren’t quite perfect for my situation:

  • It makes hardcoded assumptions about your test naming convention. For some reason we seem to have developed a local test suite naming convention of *Tests.java, instead of the more normal *Test.java or Test*.java.
  • It generates a single page of output, which gets unwieldy when you have a large number of tests
  • It flattens the package structure, which makes it hard to find the specs for a particular class, especially if there are similarly-named test suites in different packages.
  • It doesn’t include tests/specs which are inherited from a parent class.

While I could have probably solved most of these by modifying the code for TestDox, it got me thinking about whether there might be a different way of doing it. After a few false starts, I settled on the idea of writing a custom stylesheet for the JUnitReport ant task.

What I ended up with was the file below:

[xml] xmlns:lxslt="http://xml.apache.org/xslt"
xmlns:redirect="http://xml.apache.org/xalan/redirect"
xmlns:stringutils="xalan://org.apache.tools.ant.util.StringUtils"
xmlns:regexp="com.linkwerk.util.Regexp"
extension-element-prefixes="redirect regexp">

















select="./testsuite[not(./@package = preceding-sibling::testsuite/@package)]">

















</p> <h2>Frame Alert</h2> <p> This document is designed to be viewed using the frames feature. If<br /> you see this message, you are using a non-frame-capable web<br /> client. </p> <p>



font:normal 68% verdana,arial,helvetica;
color:#000000;
}
table tr td, table tr th {
font-size: 68%;
}

p {
line-height:1.5em;
margin-top:0.5em; margin-bottom:1.0em;
}
h1 {
margin: 0px 0px 5px; font: 165% verdana,arial,helvetica
}
h2 {
margin-top: 1em; margin-bottom: 0.5em; font: bold 125% verdana,arial,helvetica
}]]>



href="stylesheet.css"/>


Behaviour specifications

Select a package on the left to view the specifications for classes in
that package.





href="stylesheet.css"/>


Packages

select="testsuite[not(./@package = preceding-sibling::testsuite/@package)]"
mode="all.packages">









.html

packageFrame











href="stylesheet.css"/>
Behaviour specifications:<br /> <xsl:value-of select="$local-name"/>

Behaviour specifications:


select="/testsuites/testsuite[@package = $name]"/>








  • Derived from reports generated by
    JUnit and
    Ant.






    default-package





    select="regexp:replace(regexp:replace(string($name), '^Test', '', ''), 'Tests?$', '', '')"/>

















    select="regexp:replace(string($name), '^test', '', '')"/>














    select="normalize-space(regexp:replace(regexp:replace(string($str), '([A-Z])', 'g', ' $1'), '([^0-9])([0-9])', 'g', '$1 $2'))"/>




    select="translate($str, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>

    [/xml]

    To use it, simply save junit-frames.xsl to a convenient directory, and point your ant JunitReport task to that directory (xslt in the example below). If you’ve already run a “normal” JunitReport, you’ll need to tell it to ignore the suites file that this creates:

    [xml]


    [/xml]

    The only slight gotcha is that it relies on the Linkwerk regular expression extension, which means you need to have lw-regexp-util-1.0.0.jar in your classpath when you run ant (either by copying it to $ANT_HOME/lib, or by having it in the system classpath when you run ant). As far as I can figure, you can’t work round this using a taskdef, because of the same classloader issues that mean you always end up copying junit.jar into ant’s lib dir too.

    What you should get is a report with the package names listed in the left frame, linked to a page for each package containing its specs. So for example, if you a test suite like this:
    [java]package org.whoever.foo;

    import junit.framework.TestCase;

    public class TestANewlyInitialisedFoo extends TestCase {

    public void testShouldHaveZeroLength() {

    }

    public void testShouldHaveNoMembers() {

    }

    public void testShouldThrowExceptionOnPop() {

    }
    }[/java]

    You’ll end up with a section in the org.whoever.foo report looking a bit like this:

    A newly initialised foo

    • should have zero length
    • should have no members
    • should throw exception on pop

    Here’s a screenshot of the actual output. Don’t pay too much attention to the actual test names, most of which weren’t written using a BDD approach.

    picture-1.png

    Written by Kerry

    September 25th, 2006 at 11:17 am

    Posted in Agile,Java,Software

    5 Responses to 'An alternative approach to creating specs from JUnit tests'

    Subscribe to comments with RSS or TrackBack to 'An alternative approach to creating specs from JUnit tests'.

    1. [...] Here’s the output from running the original junit report through a stylesheet: Abstract pieman log [...]

    2. [...] Venendo ad un po’ di codice, il primo passo per incamminarsi su questa strada può essere quello di utilizzare un semplice xsl sui report prodotti da JUnit, per cominciare a misurare quanto ad oggi, siamo orientati alle specifiche ed ai comportamenti, invece che alle classi ed ai metodi. Tale xsl assume che ogni test JUnit sia una collezione di specifiche, ad esempio scritta un questo modo: Java [Show Styled Code]: [...]

    3. Don’t you think it’s idiocy to use 2000-feet-high divs with horizontal scrollbar below? To scroll horizontally it’s first lines, one must scroll the page down, and then up.

      Vassily Ivanovitsch Poupkine

      9 Feb 07 at 10:01 pm

    4. Yeah, it’s not ideal. Do you know of a better syntax highlighting plugin for WordPress?

      Of course, it’s not an issue if you have a Mighty Mouse ;-)

      Kerry

      9 Feb 07 at 10:11 pm

    5. Don’t you think it’s idiocy to use 2000-feet-high divs with horizontal scrollbar below?

      OK, I’ve tweaked the CSS for IG Syntax Highlighter a little from the defaults. Hopefully that’s better.

      Kerry

      11 Feb 07 at 7:14 pm

    Leave a Reply