Steve talks about a feature in Py.test: remember which tests failed the last time and only test these on the next run. He also hints how we could use Ant's test runner to do the same with JUnit. Well, I think we are already there:

1. Save to a file a list of all tests classes that contained a failing test

We can use a custom <formatter> for this. Without the gory details of error handling, it basically would look like

// abusing org.apache.tools.ant.taskdefs.optional.junit.SummaryJUnitResultFormatter as NullObject Adapter
public class FailureRecorder extends SummaryJUnitResultFormatter {

    // will hold class names of failed tests, we don't need duplicates
    private HashSet failedTests = new HashSet();

    // out is private in SummaryJUnitResultFormatter
    private OutputStream out;

    // out is private in SummaryJUnitResultFormatter, intercept setter
    public void setOutput(OutputStream out) {
        this.out = out;
    }

    public void addFailure(Test test, Throwable t) {
        add(test);
    }

    public void addError(Test test, Throwable t) {
        add(test);
    }

    private void add(Test test) {
        // this relies on Test being the actual test class and not a TestSuite
        // or any other decorator
        String c = test.getClass().getName().replace('.', '/');
        failedTests.add(c + ".class");
    }

    public void endTestSuite(JUnitTest suite) {
        if (out != null && failedTests.size() > 0) {
            PrintWriter w = new PrintWriter(new OutputStreamWriter(out));
            Iterator iter = failedTests.iterator();
            while (iter.hasNext()) {
                w.println(iter.next());
            }
        }
    }
}

This would leave us with a file holding the class file names of all failing tests in a format suitable for <fileset>'s includesfile attribute.

Unfortunately we'll have one file per TestSuite, which means one file per test class in normal operation mode. The easiest way to join them is using the <concat> task afterwards. So the full sequence would look like

  <junit ...>
    ...
    <batchtest todir="reports-dir">
       ...
    </batchtest>
    <formatter classname="FailureRecorder" extension="failures"/>
  </junit>
  <concat destfile="last-failures" fixlastline="true">
    <fileset dir="reports-dir" includes="*.failures" id="failing-tests"/>
  </concat>
  <delete>
    <fileset refid="failing-tests"/>
  </delete>
2. When rerunning, build up a fileset that only contains those test classes.

Trivial, use the file just created in

  <junit ...>
    <batchtest>
      <fileset dir="my-compiled-tests" includesfile="last-failures"/>
    </batchtest>
  </junit>

It may be worth to brush up the code a little and include such a formatter with Ant.

Updated since the first version would have written multiple files.

path: /en/Apache/Ant | #