Wednesday, June 8, 2011

JUnit XML Output Without Ant

It's fairly common for Continuous Integration (CI) tools (e.g., Jenkins) to run unit tests from a testing framework (e.g., JUnit) and display their results.  JUnit, in particular, has an XML output format that is accepted by result formatters (e.g, JUnitReport, aforementioned CI tools, etc.).  The XML can be produced quite easily from an Apache Ant task with the following:

     <target name="test"> 
       <mkdir dir="${result_dir}"/> 
       <junit fork="no" printsummary="yes" haltonfailure="no"> 
          <batchtest fork="no" todir="${result_dir}" > 
             <fileset dir="build"> 
                <include name="**/*Test.class" /> 
             </fileset> 
          </batchtest> 
          <formatter type="xml" /> 
          <classpath refid="classpath" /> 
       </junit> 
    </target>

But what if you don't want to use Ant as your primary build tool?  I found that producing the XML output was undocumented by JUnit, so I did some digging.

It turns out that the XML output format isn't defined by JUnit, but by Apache Ant.  Ant has its own JUnit TestRunner and Formatter that produce the XML output.  Some reverse engineering showed that I can produce simple console output using the following command-line structure:

# java -classpath .:/usr/share/ant/lib/ant.jar:\
 /usr/share/ant/lib/ant-junit.jar:lib/junit-4.9b2.jar \ 
 org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner  \ 
 HelloTest \ 
 formatter=org.apache.tools.ant.taskdefs.optional.junit.SummaryJUnitResultFormatter  \ 
 showoutput=true

...and the output is:

Running HelloTest
Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.015 sec

You'll notice that I needed a few things in my classpath:
  • My test class (HelloTest)
  • Any classes that the test class uses
  • Apache Ant & Ant's JUnit Task (from default Ant install)
  • JUnit
The main class org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner is from the Ant JUnit task jar and it expects (at the bare minimum) a test class (i.e., a set of unit tests).


It also expects a series of key/value pairs which explain what to output and how it should be formatted.  The most simple set includes a "formatter" class and a boolean "showoutput."


If instead, you want to produce XML output, all you need is to replace the "formatter" above with: 

 formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,\
 ${PATH_TO_TEST_OUTPUT_DIRECTORY}/TEST-HelloTest.xml
...which looks like:
# java -classpath .:/usr/share/ant/lib/ant.jar:\
 /usr/share/ant/lib/ant-junit.jar:lib/junit-4.9b2.jar \  
 org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner  \ 
 HelloTest \ 
 formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,\
 ${PATH_TO_TEST_OUTPUT_DIRECTORY}/TEST-HelloTest.xml

This will produce an XML file which contains the results of the unit test(s).

1 comment: