FileDocCategorySizeDatePackage
JUnitTestRunner.javaAPI DocApache Ant 1.7037605Wed Dec 13 06:16:22 GMT 2006org.apache.tools.ant.taskdefs.optional.junit

JUnitTestRunner

public class JUnitTestRunner extends Object implements JUnitTaskMirror.JUnitTestRunnerMirror, TestListener
Simple Testrunner for JUnit that runs all tests of a testsuite.

This TestRunner expects a name of a TestCase class as its argument. If this class provides a static suite() method it will be called and the resulting Test will be run. So, the signature should be


public static junit.framework.Test suite()

If no such method exists, all public methods starting with "test" and taking no argument will be run.

Summary output is generated at the end.

since
Ant 1.2

Fields Summary
private Vector
formatters
Holds the registered formatters.
private TestResult
res
Collects TestResults.
private static boolean
filtertrace
Do we filter junit.*.* stack frames out of failure and error exceptions.
private boolean
showOutput
Do we send output to System.out/.err in addition to the formatters?
private boolean
outputToFormatters
private org.apache.tools.ant.types.Permissions
perm
The permissions set for the test to run.
private static final String[]
DEFAULT_TRACE_FILTERS
private boolean
haltOnError
Do we stop on errors.
private boolean
haltOnFailure
Do we stop on test failures.
private int
retCode
Returncode
private JUnitTest
junitTest
The TestSuite we are currently running.
private PrintStream
systemError
output written during the test
private PrintStream
systemOut
Error output during the test
private boolean
forked
is this runner running in forked mode?
private static boolean
multipleTests
Running more than one test suite?
private ClassLoader
loader
ClassLoader passed in in non-forked mode.
private boolean
logTestListenerEvents
Do we print TestListener events?
private boolean
junit4
Turned on if we are using JUnit 4 for this test suite. see #38811
private static String
crashFile
The file used to indicate that the build crashed. File will be empty in case the build did not crash.
private PrintStream
savedOut
private static Vector
fromCmdLine
Constructors Summary
public JUnitTestRunner(JUnitTest test, boolean haltOnError, boolean filtertrace, boolean haltOnFailure)
Constructor for fork=true or when the user hasn't specified a classpath.

param
test the test to run.
param
haltOnError whether to stop the run if an error is found.
param
filtertrace whether to filter junit.*.* stack frames out of exceptions
param
haltOnFailure whether to stop the run if failure is found.


                                                            
        
                               
        this(test, haltOnError, filtertrace, haltOnFailure, false);
    
public JUnitTestRunner(JUnitTest test, boolean haltOnError, boolean filtertrace, boolean haltOnFailure, boolean showOutput)
Constructor for fork=true or when the user hasn't specified a classpath.

param
test the test to run.
param
haltOnError whether to stop the run if an error is found.
param
filtertrace whether to filter junit.*.* stack frames out of exceptions
param
haltOnFailure whether to stop the run if failure is found.
param
showOutput whether to send output to System.out/.err as well as formatters.

        this(test, haltOnError, filtertrace, haltOnFailure, showOutput, false);
    
public JUnitTestRunner(JUnitTest test, boolean haltOnError, boolean filtertrace, boolean haltOnFailure, boolean showOutput, boolean logTestListenerEvents)
Constructor for fork=true or when the user hasn't specified a classpath.

param
test the test to run.
param
haltOnError whether to stop the run if an error is found.
param
filtertrace whether to filter junit.*.* stack frames out of exceptions
param
haltOnFailure whether to stop the run if failure is found.
param
showOutput whether to send output to System.out/.err as well as formatters.
param
logTestListenerEvents whether to print TestListener events.
since
Ant 1.7

        this(test, haltOnError, filtertrace, haltOnFailure, showOutput,
             logTestListenerEvents, null);
    
public JUnitTestRunner(JUnitTest test, boolean haltOnError, boolean filtertrace, boolean haltOnFailure, ClassLoader loader)
Constructor to use when the user has specified a classpath.

param
test the test to run.
param
haltOnError whether to stop the run if an error is found.
param
filtertrace whether to filter junit.*.* stack frames out of exceptions
param
haltOnFailure whether to stop the run if failure is found.
param
loader the classloader to use running the test.

        this(test, haltOnError, filtertrace, haltOnFailure, false, loader);
    
public JUnitTestRunner(JUnitTest test, boolean haltOnError, boolean filtertrace, boolean haltOnFailure, boolean showOutput, ClassLoader loader)
Constructor to use when the user has specified a classpath.

param
test the test to run.
param
haltOnError whether to stop the run if an error is found.
param
filtertrace whether to filter junit.*.* stack frames out of exceptions
param
haltOnFailure whether to stop the run if failure is found.
param
showOutput whether to send output to System.out/.err as well as formatters.
param
loader the classloader to use running the test.

        this(test, haltOnError, filtertrace, haltOnFailure, showOutput,
             false, loader);
    
public JUnitTestRunner(JUnitTest test, boolean haltOnError, boolean filtertrace, boolean haltOnFailure, boolean showOutput, boolean logTestListenerEvents, ClassLoader loader)
Constructor to use when the user has specified a classpath.

param
test the test to run.
param
haltOnError whether to stop the run if an error is found.
param
filtertrace whether to filter junit.*.* stack frames out of exceptions
param
haltOnFailure whether to stop the run if failure is found.
param
showOutput whether to send output to System.out/.err as well as formatters.
param
logTestListenerEvents whether to print TestListener events.
param
loader the classloader to use running the test.
since
Ant 1.7

        JUnitTestRunner.filtertrace = filtertrace;
        this.junitTest = test;
        this.haltOnError = haltOnError;
        this.haltOnFailure = haltOnFailure;
        this.showOutput = showOutput;
        this.logTestListenerEvents = logTestListenerEvents;
        this.loader = loader;
    
Methods Summary
public voidaddError(junit.framework.Test test, java.lang.Throwable t)
Interface TestListener.

An error occurred while running the test.

param
test the test.
param
t the error thrown by the test.

        String testName = JUnitVersionHelper.getTestCaseName(test);
        logTestListenerEvent("addError(" + testName + ", " + t.getMessage() + ")");
        if (haltOnError) {
            res.stop();
        }
    
public voidaddFailure(junit.framework.Test test, java.lang.Throwable t)
Interface TestListener for JUnit <= 3.4.

A Test failed.

param
test the test.
param
t the exception thrown by the test.

        String testName = JUnitVersionHelper.getTestCaseName(test);
        logTestListenerEvent("addFailure(" + testName + ", " + t.getMessage() + ")");
        if (haltOnFailure) {
            res.stop();
        }
    
public voidaddFailure(junit.framework.Test test, junit.framework.AssertionFailedError t)
Interface TestListener for JUnit > 3.4.

A Test failed.

param
test the test.
param
t the assertion thrown by the test.

        addFailure(test, (Throwable) t);
    
public voidaddFormatter(JUnitResultFormatter f)
Add a formatter.

param
f the formatter to add.

        formatters.addElement(f);
    
public voidaddFormatter(JUnitTaskMirror.JUnitResultFormatterMirror f)
{@inheritDoc}.

        formatters.addElement((JUnitResultFormatter) f);
    
private static voidcreateAndStoreFormatter(java.lang.String line)
Line format is: formatter=(,)?

        FormatterElement fe = new FormatterElement();
        int pos = line.indexOf(',");
        if (pos == -1) {
            fe.setClassname(line);
            fe.setUseFile(false);
        } else {
            fe.setClassname(line.substring(0, pos));
            fe.setUseFile(true);
            if (!multipleTests) {
                fe.setOutfile(new File(line.substring(pos + 1)));
            } else {
                int fName = line.indexOf(IGNORED_FILE_NAME);
                if (fName > -1) {
                    fe.setExtension(line
                                    .substring(fName
                                               + IGNORED_FILE_NAME.length()));
                }
            }
        }
        fromCmdLine.addElement(fe);
    
public voidendTest(junit.framework.Test test)
Interface TestListener.

A Test is finished.

param
test the test.

        String testName = JUnitVersionHelper.getTestCaseName(test);
        logTestListenerEvent("endTest(" + testName + ")");
    
private static booleanfilterLine(java.lang.String line)

        for (int i = 0; i < DEFAULT_TRACE_FILTERS.length; i++) {
            if (line.indexOf(DEFAULT_TRACE_FILTERS[i]) != -1) {
                return true;
            }
        }
        return false;
    
public static java.lang.StringfilterStack(java.lang.String stack)
Filters stack frames from internal JUnit and Ant classes

param
stack the stack trace to filter.
return
the filtered stack.

        if (!filtertrace) {
            return stack;
        }
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        StringReader sr = new StringReader(stack);
        BufferedReader br = new BufferedReader(sr);

        String line;
        try {
            while ((line = br.readLine()) != null) {
                if (!filterLine(line)) {
                    pw.println(line);
                }
            }
        } catch (Exception e) {
            return stack; // return the stack unfiltered
        }
        return sw.toString();
    
private int[]findJUnit4FailureErrorCount(junit.framework.TestResult res)
Use instead of TestResult.get{Failure,Error}Count on JUnit 4, since the adapter claims that all failures are errors.

since
Ant 1.7

        int failures = 0;
        int errors = 0;
        Enumeration e = res.failures();
        while (e.hasMoreElements()) {
            e.nextElement();
            failures++;
        }
        e = res.errors();
        while (e.hasMoreElements()) {
            Throwable t = ((TestFailure) e.nextElement()).thrownException();
            if (t instanceof AssertionFailedError
                || t.getClass().getName().equals("java.lang.AssertionError")) {
                failures++;
            } else {
                errors++;
            }
        }
        return new int[] {failures, errors};
    
private voidfireEndTestSuite()

        for (int i = 0; i < formatters.size(); i++) {
            ((JUnitResultFormatter) formatters.elementAt(i))
                .endTestSuite(junitTest);
        }
    
private voidfireStartTestSuite()

        for (int i = 0; i < formatters.size(); i++) {
            ((JUnitResultFormatter) formatters.elementAt(i))
                .startTestSuite(junitTest);
        }
    
public static java.lang.StringgetFilteredTrace(java.lang.Throwable t)
Returns a filtered stack trace. This is ripped out of junit.runner.BaseTestRunner.

param
t the exception to filter.
return
the filtered stack trace.

        String trace = StringUtils.getStackTrace(t);
        return JUnitTestRunner.filterStack(trace);
    
public intgetRetCode()
Returns what System.exit() would return in the standalone version.

return
2 if errors occurred, 1 if tests failed else 0.

        return retCode;
    
public voidhandleErrorFlush(java.lang.String output)
{@inheritDoc}.

        if (systemError != null) {
            systemError.print(output);
        }
    
public voidhandleErrorOutput(java.lang.String output)
{@inheritDoc}.

        if (systemError != null) {
            systemError.print(output);
        }
    
public voidhandleFlush(java.lang.String output)
{@inheritDoc}.

        if (systemOut != null) {
            systemOut.print(output);
        }
    
public inthandleInput(byte[] buffer, int offset, int length)
Handle input.

param
buffer not used.
param
offset not used.
param
length not used.
return
-1 always.
throws
IOException never.
see
org.apache.tools.ant.Task#handleInput(byte[], int, int)
since
Ant 1.6

        return -1;
    
public voidhandleOutput(java.lang.String output)
Handle a string destined for standard output.

param
output the string to output

        if (!logTestListenerEvents && output.startsWith(JUnitTask.TESTLISTENER_PREFIX)) {
            // ignore
        } else if (systemOut != null) {
            systemOut.print(output);
        }
    
private static intlaunch(JUnitTest t, boolean haltError, boolean stackfilter, boolean haltFail, boolean showOut, boolean outputToFormat, boolean logTestListenerEvents, java.util.Properties props)

since
Ant 1.6.2

        t.setProperties(props);
        JUnitTestRunner runner =
            new JUnitTestRunner(t, haltError, stackfilter, haltFail, showOut,
                                logTestListenerEvents, null);
        runner.forked = true;
        runner.outputToFormatters = outputToFormat;
        transferFormatters(runner, t);

        runner.run();
        return runner.getRetCode();
     
private voidlogTestListenerEvent(java.lang.String msg)

        PrintStream out = savedOut != null ? savedOut : System.out;
        if (logTestListenerEvents) {
            out.flush();
            out.println(JUnitTask.TESTLISTENER_PREFIX + msg);
            out.flush();
        }
    
public static voidmain(java.lang.String[] args)
Entry point for standalone (forked) mode. Parameters: testcaseclassname plus parameters in the format key=value, none of which is required.
keydescriptiondefault value
haltOnErrorhalt test on errors?false
haltOnFailurehalt test on failures?false
formatterA JUnitResultFormatter given as classname,filename. If filename is ommitted, System.out is assumed.none
showoutputsend output to System.err/.out as well as to the formatters?false
logtestlistenereventslog TestListener events to System.out.false

param
args the command line arguments.
throws
IOException on error.

        boolean haltError = false;
        boolean haltFail = false;
        boolean stackfilter = true;
        Properties props = new Properties();
        boolean showOut = false;
        boolean outputToFormat = true;
        boolean logTestListenerEvents = false;


        if (args.length == 0) {
            System.err.println("required argument TestClassName missing");
            System.exit(ERRORS);
        }

        if (args[0].startsWith(Constants.TESTSFILE)) {
            multipleTests = true;
            args[0] = args[0].substring(Constants.TESTSFILE.length());
        }

        for (int i = 1; i < args.length; i++) {
            if (args[i].startsWith(Constants.HALT_ON_ERROR)) {
                haltError = Project.toBoolean(args[i].substring(Constants.HALT_ON_ERROR.length()));
            } else if (args[i].startsWith(Constants.HALT_ON_FAILURE)) {
                haltFail = Project.toBoolean(args[i].substring(Constants.HALT_ON_FAILURE.length()));
            } else if (args[i].startsWith(Constants.FILTERTRACE)) {
                stackfilter = Project.toBoolean(args[i].substring(Constants.FILTERTRACE.length()));
            } else if (args[i].startsWith(Constants.CRASHFILE)) {
                crashFile = args[i].substring(Constants.CRASHFILE.length());
                registerTestCase(Constants.BEFORE_FIRST_TEST);
            } else if (args[i].startsWith(Constants.FORMATTER)) {
                try {
                    createAndStoreFormatter(args[i].substring(Constants.FORMATTER.length()));
                } catch (BuildException be) {
                    System.err.println(be.getMessage());
                    System.exit(ERRORS);
                }
            } else if (args[i].startsWith(Constants.PROPSFILE)) {
                FileInputStream in = new FileInputStream(args[i]
                                                         .substring(Constants.PROPSFILE.length()));
                props.load(in);
                in.close();
            } else if (args[i].startsWith(Constants.SHOWOUTPUT)) {
                showOut = Project.toBoolean(args[i].substring(Constants.SHOWOUTPUT.length()));
            } else if (args[i].startsWith(Constants.LOGTESTLISTENEREVENTS)) {
                logTestListenerEvents = Project.toBoolean(
                    args[i].substring(Constants.LOGTESTLISTENEREVENTS.length()));
            } else if (args[i].startsWith(Constants.OUTPUT_TO_FORMATTERS)) {
                outputToFormat = Project.toBoolean(
                    args[i].substring(Constants.OUTPUT_TO_FORMATTERS.length()));
            }
        }

        // Add/overlay system properties on the properties from the Ant project
        Hashtable p = System.getProperties();
        for (Enumeration e = p.keys(); e.hasMoreElements();) {
            Object key = e.nextElement();
            props.put(key, p.get(key));
        }

        int returnCode = SUCCESS;
        if (multipleTests) {
            try {
                java.io.BufferedReader reader =
                    new java.io.BufferedReader(new java.io.FileReader(args[0]));
                String testCaseName;
                int code = 0;
                boolean errorOccurred = false;
                boolean failureOccurred = false;
                String line = null;
                while ((line = reader.readLine()) != null) {
                    StringTokenizer st = new StringTokenizer(line, ",");
                    testCaseName = st.nextToken();
                    JUnitTest t = new JUnitTest(testCaseName);
                    t.setTodir(new File(st.nextToken()));
                    t.setOutfile(st.nextToken());
                    code = launch(t, haltError, stackfilter, haltFail,
                                  showOut, outputToFormat,
                                  logTestListenerEvents, props);
                    errorOccurred = (code == ERRORS);
                    failureOccurred = (code != SUCCESS);
                    if (errorOccurred || failureOccurred) {
                        if ((errorOccurred && haltError)
                            || (failureOccurred && haltFail)) {
                            registerNonCrash();
                            System.exit(code);
                        } else {
                            if (code > returnCode) {
                                returnCode = code;
                            }
                            System.out.println("TEST " + t.getName()
                                               + " FAILED");
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            returnCode = launch(new JUnitTest(args[0]), haltError,
                                stackfilter, haltFail,
                                showOut, outputToFormat,
                                logTestListenerEvents, props);
        }

        registerNonCrash();
        System.exit(returnCode);
    
private static voidregisterNonCrash()

since
Ant 1.7

        if (crashFile != null) {
            FileWriter out = null;
            try {
                out = new FileWriter(crashFile);
                out.write(Constants.TERMINATED_SUCCESSFULLY + "\n");
                out.flush();
            } finally {
                if (out != null) {
                    out.close();
                }
            }
        }
    
private static voidregisterTestCase(java.lang.String testCase)

        if (crashFile != null) {
            try {
                FileWriter out = null;
                try {
                    out = new FileWriter(crashFile);
                    out.write(testCase + "\n");
                    out.flush();
                } finally {
                    if (out != null) {
                        out.close();
                    }
                }
            } catch (IOException e) {
                // ignored.
            }
        }
    
public voidrun()
Run the test.


            
       
        res = new TestResult();
        res.addListener(wrapListener(this));
        for (int i = 0; i < formatters.size(); i++) {
            res.addListener(wrapListener((TestListener) formatters.elementAt(i)));
        }

        ByteArrayOutputStream errStrm = new ByteArrayOutputStream();
        systemError = new PrintStream(errStrm);

        ByteArrayOutputStream outStrm = new ByteArrayOutputStream();
        systemOut = new PrintStream(outStrm);

        PrintStream savedErr = null;

        if (forked) {
            if (!outputToFormatters) {
                if (!showOutput) {
                    savedOut = System.out;
                    savedErr = System.err;
                    System.setOut(
                        new PrintStream(
                            new OutputStream() {
                                public void write(int b) {
                                }
                            }));
                    System.setErr(
                        new PrintStream(
                            new OutputStream() {
                                public void write(int b) {
                                }
                            }));
                }
            } else {
                savedOut = System.out;
                savedErr = System.err;
                if (!showOutput) {
                    System.setOut(systemOut);
                    System.setErr(systemError);
                } else {
                    System.setOut(new PrintStream(
                                      new TeeOutputStream(savedOut, systemOut)
                                      )
                                  );
                    System.setErr(new PrintStream(
                                      new TeeOutputStream(savedErr,
                                                          systemError)
                                      )
                                  );
                }
                perm = null;
            }
        } else {
            if (perm != null) {
                perm.setSecurityManager();
            }
        }

        Test suite = null;
        Throwable exception = null;
        boolean startTestSuiteSuccess = false;

        try {

            try {
                Class testClass = null;
                if (loader == null) {
                    testClass = Class.forName(junitTest.getName());
                } else {
                    testClass = Class.forName(junitTest.getName(), true,
                                              loader);
                }

                // check for a static suite method first, even when using
                // JUnit 4
                Method suiteMethod = null;
                try {
                    // check if there is a suite method
                    suiteMethod = testClass.getMethod("suite", new Class[0]);
                } catch (NoSuchMethodException e) {
                    // no appropriate suite method found. We don't report any
                    // error here since it might be perfectly normal.
                }

                if (suiteMethod != null) {
                    // if there is a suite method available, then try
                    // to extract the suite from it. If there is an error
                    // here it will be caught below and reported.
                    suite = (Test) suiteMethod.invoke(null, new Class[0]);

                } else {
                    Class junit4TestAdapterClass = null;

                    // Check for JDK 5 first. Will *not* help on JDK 1.4
                    // if only junit-4.0.jar in CP because in that case
                    // linkage of whole task will already have failed! But
                    // will help if CP has junit-3.8.2.jar:junit-4.0.jar.

                    // In that case first C.fN will fail with CNFE and we
                    // will avoid UnsupportedClassVersionError.

                    try {
                        Class.forName("java.lang.annotation.Annotation");
                        if (loader == null) {
                            junit4TestAdapterClass =
                                Class.forName("junit.framework.JUnit4TestAdapter");
                        } else {
                            junit4TestAdapterClass =
                                Class.forName("junit.framework.JUnit4TestAdapter",
                                              true, loader);
                        }
                    } catch (ClassNotFoundException e) {
                        // OK, fall back to JUnit 3.
                    }
                    junit4 = junit4TestAdapterClass != null;

                    if (junit4) {
                        // Let's use it!
                        suite =
                            (Test) junit4TestAdapterClass
                            .getConstructor(new Class[] {Class.class}).
                            newInstance(new Object[] {testClass});
                    } else {
                        // Use JUnit 3.

                        // try to extract a test suite automatically this
                        // will generate warnings if the class is no
                        // suitable Test
                        suite = new TestSuite(testClass);
                    }

                }

            } catch (Throwable e) {
                retCode = ERRORS;
                exception = e;
            }

            long start = System.currentTimeMillis();

            fireStartTestSuite();
            startTestSuiteSuccess = true;
            if (exception != null) { // had an exception constructing suite
                for (int i = 0; i < formatters.size(); i++) {
                    ((TestListener) formatters.elementAt(i))
                        .addError(null, exception);
                }
                junitTest.setCounts(1, 0, 1);
                junitTest.setRunTime(0);
            } else {
                try {
                    logTestListenerEvent("tests to run: " + suite.countTestCases());
                    suite.run(res);
                } finally {
                    if (junit4) {
                        int[] cnts = findJUnit4FailureErrorCount(res);
                        junitTest.setCounts(res.runCount(), cnts[0], cnts[1]);
                    } else {
                        junitTest.setCounts(res.runCount(), res.failureCount(),
                                res.errorCount());
                    }
                    junitTest.setRunTime(System.currentTimeMillis() - start);
                }
            }
        } finally {
            if (perm != null) {
                perm.restoreSecurityManager();
            }
            if (savedOut != null) {
                System.setOut(savedOut);
            }
            if (savedErr != null) {
                System.setErr(savedErr);
            }

            systemError.close();
            systemError = null;
            systemOut.close();
            systemOut = null;
            if (startTestSuiteSuccess) {
                sendOutAndErr(new String(outStrm.toByteArray()),
                              new String(errStrm.toByteArray()));
            }
        }
        fireEndTestSuite();

        if (retCode != SUCCESS || res.errorCount() != 0) {
            retCode = ERRORS;
        } else if (res.failureCount() != 0) {
            retCode = FAILURES;
        }
    
private voidsendOutAndErr(java.lang.String out, java.lang.String err)

        for (int i = 0; i < formatters.size(); i++) {
            JUnitResultFormatter formatter =
                ((JUnitResultFormatter) formatters.elementAt(i));

            formatter.setSystemOutput(out);
            formatter.setSystemError(err);
        }
    
public voidsetPermissions(org.apache.tools.ant.types.Permissions permissions)
Permissions for the test run.

since
Ant 1.6
param
permissions the permissions to use.

        perm = permissions;
    
public voidstartTest(junit.framework.Test t)
Interface TestListener.

A new Test is started.

param
t the test.

        String testName = JUnitVersionHelper.getTestCaseName(t);
        logTestListenerEvent("startTest(" + testName + ")");
    
private static voidtransferFormatters(org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner runner, JUnitTest test)


        
                                             
        runner.addFormatter(new JUnitResultFormatter() {

            public void startTestSuite(JUnitTest suite) throws BuildException {
            }

            public void endTestSuite(JUnitTest suite) throws BuildException {
            }

            public void setOutput(OutputStream out) {
            }

            public void setSystemOutput(String out) {
            }

            public void setSystemError(String err) {
            }

            public void addError(Test arg0, Throwable arg1) {
            }

            public void addFailure(Test arg0, AssertionFailedError arg1) {
            }

            public void endTest(Test arg0) {
            }

            public void startTest(Test arg0) {
                registerTestCase(JUnitVersionHelper.getTestCaseName(arg0));
            }
        });
        for (int i = 0; i < fromCmdLine.size(); i++) {
            FormatterElement fe = (FormatterElement) fromCmdLine.elementAt(i);
            if (multipleTests && fe.getUseFile()) {
                File destFile =
                    new File(test.getTodir(),
                             test.getOutfile() + fe.getExtension());
                fe.setOutfile(destFile);
            }
            runner.addFormatter((JUnitResultFormatter) fe.createFormatter());
        }
    
private junit.framework.TestListenerwrapListener(junit.framework.TestListener testListener)
Modifies a TestListener when running JUnit 4: treats AssertionFailedError as a failure not an error.

since
Ant 1.7

        return new TestListener() {
            public void addError(Test test, Throwable t) {
                if (junit4 && t instanceof AssertionFailedError) {
                    // JUnit 4 does not distinguish between errors and failures
                    // even in the JUnit 3 adapter.
                    // So we need to help it a bit to retain compatibility for JUnit 3 tests.
                    testListener.addFailure(test, (AssertionFailedError) t);
                } else if (junit4 && t.getClass().getName().equals("java.lang.AssertionError")) {
                    // Not strictly necessary but probably desirable.
                    // JUnit 4-specific test GUIs will show just "failures".
                    // But Ant's output shows "failures" vs. "errors".
                    // We would prefer to show "failure" for things that logically are.
                    try {
                        String msg = t.getMessage();
                        AssertionFailedError failure = msg != null
                            ? new AssertionFailedError(msg) : new AssertionFailedError();
                        // To compile on pre-JDK 4 (even though this should always succeed):
                        Method initCause = Throwable.class.getMethod(
                            "initCause", new Class[] {Throwable.class});
                        initCause.invoke(failure, new Object[] {t});
                        testListener.addFailure(test, failure);
                    } catch (Exception e) {
                        // Rats.
                        e.printStackTrace(); // should not happen
                        testListener.addError(test, t);
                    }
                } else {
                    testListener.addError(test, t);
                }
            }
            public void addFailure(Test test, AssertionFailedError t) {
                testListener.addFailure(test, t);
            }
            public void addFailure(Test test, Throwable t) { // pre-3.4
                if (t instanceof AssertionFailedError) {
                    testListener.addFailure(test, (AssertionFailedError) t);
                } else {
                    testListener.addError(test, t);
                }
            }
            public void endTest(Test test) {
                testListener.endTest(test);
            }
            public void startTest(Test test) {
                testListener.startTest(test);
            }
        };