Hello Specs2 JUnit, Farewell Henkelmann TestListener

Out of the box, SBT 10.1 doesn't give you test results in JUnit output. This is a problem for anyone using Jenkins to process test results. Fortunately, last November, Christoph Henkelmann released a plugin to SBT that plugs in to the test execution life cycle of SBT, http://henkelmann.eu/junit_xml_listener.  This was great, but had a few bugs with inconsistent results and JUnit data ending up in the wrong file or XML being badly formatted. These bugs occurred inconsistently and infrequently enough to be only a minor annoyance.

Over this past summer, specs2 added a JUnit output option for its test results. At the time, the documentation didn't fully explain the necessary integration points. So I'll explain what I did to get it working. Most of this information is now available at, http://etorreborre.github.com/specs2/guide/org.specs2.guide.Runners.html if you search for "junit".

// Put this in your SBT build file to output to both console
// ...and junit files console is helpful so that you can see the
// ...output in jenkins build history
testOptions in Test += Tests.Argument("junitxml", "console")

If you're running on the command line, you can provide SBT system arguments straight up, like

bash $> sbt junitxml

Finally, on the SBT command line, it won't work with the SBT "test" command, but it will work with the SBT "test-only" command.

sbt-command-line>test-only com.company.class.specs -- junitxml

The other cool learning that I experienced at this time, was with using SBT collections. We have several scala projects and we need to share common SBT properties between them. To accomplish this, we made our own SBT plugin and import all of its settings at the top of each project. One of the settings is the testListener SBT setting, which attaches the junitXmlListener to all our unit test output. Since, I wanted to test out the junitxml flag in only one project before fully committing to it, I couldn't outright remove the test listener for all the projects. So in order to remove only in one project, I used the SBT filter syntax: ~=

testListeners ~= { (listeners: Seq[TestReportListener]) =>
    listeners filterNot ( _.isInstanceOf[JUnitXmlTestsListener] )


Recent posts