Immediate JUnit test logging with Ant Task

2019-05-02 03:44发布

I have the following in my build.xml:

<junit fork="yes" printsummary="yes" filtertrace="yes">
    <classpath>...</classpath>
    <test name="tests.AllTests"/>
    <formatter type="plain" usefile="false"/>
</junit>

I would like the JUnit results to be reported for each test as soon as they complete, unfortunately the JUnit task only prints the test results after the whole test case has completed. The test case (AllTests) is rather large, so I have to wait quite a while for the output. Is there any way to make <junit> print individual test results immediately?

标签: ant junit
2条回答
淡お忘
2楼-- · 2019-05-02 04:33

I believe the built-in JUnit formatters buffer everything until the end. You should be able to write your own formatter implementation which extends org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter so that it flushes to STDOUT immediately, but I've never done it.

You can use this blog where the author makes a custom formatter and shows both the code and how to use it in the build.xml http://shaman-sir.wikidot.com/one-liner-output-formatter

There is also a similar SO question with similar info How do I configure JUnit Ant task to only produce output on failures?

查看更多
倾城 Initia
3楼-- · 2019-05-02 04:41

I followed dkatzel's suggestion to write my own JUnitResultFormatter. Here is the code for my JUnitFormatter:

package util;

import java.io.OutputStream;
import java.io.PrintStream;

import junit.framework.AssertionFailedError;
import junit.framework.Test;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter;
import org.apache.tools.ant.taskdefs.optional.junit.JUnitTest;

public class SimpleTestFormatter implements JUnitResultFormatter {
    private PrintStream out = System.out;

    @Override
    public void addError(Test test, Throwable error) {
        logResult(test, "ERR");
        out.println(error.getMessage());
    }

    @Override
    public void addFailure(Test test, AssertionFailedError failure) {
        logResult(test, "FAIL");
        out.println(failure.getMessage());
    }

    @Override
    public void endTest(Test test) {
        logResult(test, "PASS");
    }

    @Override
    public void startTest(Test test) { }

    @Override
    public void endTestSuite(JUnitTest testSuite) throws BuildException { }

    @Override
    public void setOutput(OutputStream out) {
        this.out = new PrintStream(out);
    }

    @Override
    public void setSystemError(String err) {
        // don't echo test error output
    }

    @Override
    public void setSystemOutput(String out) {
        // don't echo test output
    }

    @Override
    public void startTestSuite(JUnitTest testSuite) throws BuildException { }

    private void logResult(Test test, String result) {
        out.println("[" + result + "] " + String.valueOf(test));
        out.flush();
    }
}

And this is how I use it in the Ant script:

<junit fork="yes" printsummary="yes" filtertrace="yes">
    <classpath>...</classpath>
    <test name="tests.AllTests"/>
    <formatter classname="util.SimpleTestFormatter" usefile="false"/>
</junit>

Note that the class must be compiled with ant.jar and ant-junit.jar on the classpath.

查看更多
登录 后发表回答