Using JUnit with Ant

JUnit works great from Ant, as long as you don't expect graphical output in real-time. The Ant <junit> task is an Optional task, not a Core task, but with Ant 1.7, this just means you need to provide the ant-4.5.jar file. Ant 1.7 comes with wiring for the <junit> task out-of-the-box. Just specify the path to your ant-4.5.jar in your <junit> task. (There are several other ways to get it on the classpath, but this method is the last invasive, and least likely to have side-effects on your other applications).

You can download or view this complete Ant build file. The part that runs JUnit tests is captured below.

Example 8.1. Ant build file snippet

    
  <target name="unittest" description="Execute unit tests"
          depends="compile-tests">
    <ivy:cachepath conf="test" pathid="test.refid"/>
    <mkdir dir="tmp/rawtestoutput"/>
    <junit printsummary="true" failureproperty="junit.failure">
      <!-- N.b. use failureproperty instead of haltonfailure, because if we use
           the former, we will get no detailed report about the failure.
           If the test fails, the fail element below will still assure that
           the Ant run will exit with error status.
      -->
      <classpath refid="test.refid"/>
      <classpath path="classes:test-classes"/>
      <!-- Ant provides several ways to set the classpath.  The critical thing
           is just that the final classpath for the junit task must include
           the junit-4.x jar file, the test classes, and all classes referred
           to directly or indirectly by your test classes.  -->

      <batchtest todir="tmp/rawtestoutput">
        <fileset dir="test-classes"/>
        <formatter type="xml"/>
      </batchtest>
      <!-- In the unlikely case that you just have a single test class,
           use a test element like this instead of the batchtest element
           above:   <test name='com.admc.jamama.smtp.SMTPTest'/>
           You can nest the formatter inside it, just like batchtest.
      -->

      <!-- You can use sysproperty elements to pass configuration settings
           to your test classes, or to appplication classes they will run:
     <sysproperty key="targetserver.test" value="mercedes"/>
     -->
    </junit>
    <junitreport todir="tmp">
      <fileset dir="tmp/rawtestoutput"/>
      <report todir="test-reports"/>
    </junitreport>
    <fail if="junit.failure" message="Unit test(s) failed.  See reports!"/>:w
  </target>
    

This is a powerful snippet. I've used variations of this for very large, distributed Java projects. Here are the important things to notice.

How things work to generate HTML reports is.

  1. The xml formatter element nested in the junit element produces raw data XML files.

  2. The following junitreport task generates a summary XML file named TESTS-TestSuites.xml

  3. The report element nested in the junitreport taskgenerates the final HTML and css files

Sometimes you just want to see the report results on your screen. Maybe you're repeatedly running unit tests with Ant in one window, while you have your editor up, adjusting code to satisfy the tests. In that case, take out the junitreport element, and use just

    <junit printsummary="true">
or, for more detail to the screen, use a formatter but set usefile="false"

You usually do not want to set attribute showoutput="true". This sends the stderr and stdout of your test class and your target class (or whatever your test classes run) to the screen. If your classes do produce any output, it usually makes a big mess when mashed together with the JUnit output.


$Revision: 2422 $