FileDocCategorySizeDatePackage
JUnitTask.javaAPI DocApache Ant 1.7063064Wed Dec 13 06:16:20 GMT 2006org.apache.tools.ant.taskdefs.optional.junit

JUnitTask

public class JUnitTask extends org.apache.tools.ant.Task
Runs JUnit tests.

JUnit is a framework to create unit tests. It has been initially created by Erich Gamma and Kent Beck. JUnit can be found at http://www.junit.org.

JUnitTask can run a single specific JUnitTest using the test element.

For example, the following target
<target name="test-int-chars" depends="jar-test">
<echo message="testing international characters"/>
<junit printsummary="no" haltonfailure="yes" fork="false">
<classpath refid="classpath"/>
<formatter type="plain" usefile="false" />
<test name="org.apache.ecs.InternationalCharTest" />
</junit>
</target>

runs a single junit test (org.apache.ecs.InternationalCharTest) in the current VM using the path with id classpath as classpath and presents the results formatted using the standard plain formatter on the command line.

This task can also run batches of tests. The batchtest element creates a BatchTest based on a fileset. This allows, for example, all classes found in directory to be run as testcases.

For example,

<target name="run-tests" depends="dump-info,compile-tests" if="junit.present">
<junit printsummary="no" haltonfailure="yes" fork="${junit.fork}">
<jvmarg value="-classic"/>
<classpath refid="tests-classpath"/>
<sysproperty key="build.tests" value="${build.tests}"/>
<formatter type="brief" usefile="false" />
<batchtest>
<fileset dir="${tests.dir}">
<include name="**/*Test*" />
</fileset>
</batchtest>
</junit>
</target>

this target finds any classes with a test directory anywhere in their path (under the top ${tests.dir}, of course) and creates JUnitTest's for each one.

Of course, <junit> and <batch> elements can be combined for more complex tests. For an example, see the ant build.xml target run-tests (the second example is an edited version).

To spawn a new Java VM to prevent interferences between different testcases, you need to enable fork. A number of attributes and elements allow you to set up how this JVM runs.

since
Ant 1.2
see
JUnitTest
see
BatchTest

Fields Summary
private static final String
CLASSPATH
private org.apache.tools.ant.types.CommandlineJava
commandline
private Vector
tests
private Vector
batchTests
private Vector
formatters
private File
dir
private Integer
timeout
private boolean
summary
private boolean
reloading
private String
summaryValue
private JUnitTaskMirror.JUnitTestRunnerMirror
runner
private boolean
newEnvironment
private org.apache.tools.ant.types.Environment
env
private boolean
includeAntRuntime
private org.apache.tools.ant.types.Path
antRuntimeClasses
private boolean
showOutput
private boolean
outputToFormatters
private File
tmpDir
private org.apache.tools.ant.AntClassLoader
classLoader
private org.apache.tools.ant.types.Permissions
perm
private ForkMode
forkMode
private boolean
splitJunit
private JUnitTaskMirror
delegate
private boolean
haltOnError
private boolean
haltOnFail
private boolean
filterTrace
private boolean
fork
private String
failureProperty
private String
errorProperty
private static final int
STRING_BUFFER_SIZE
public static final String
TESTLISTENER_PREFIX
private static final org.apache.tools.ant.util.FileUtils
FILE_UTILS
Constructors Summary
public JUnitTask()
Creates a new JUnitRunner and enables fork of a new Java VM.

throws
Exception under ??? circumstances
since
Ant 1.2

        getCommandline()
            .setClassname("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner");
    
Methods Summary
protected voidactOnTestResult(int exitValue, boolean wasKilled, JUnitTest test, java.lang.String name)
Logs information about failed tests, potentially stops processing (by throwing a BuildException) if a failure/error occurred or sets a property.

param
exitValue the exitValue of the test.
param
wasKilled if true, the test had been killed.
param
test the test in question.
param
name the name of the test.
since
Ant 1.6.2

        TestResultHolder t = new TestResultHolder();
        t.exitCode = exitValue;
        t.timedOut = wasKilled;
        actOnTestResult(t, test, name);
    
protected voidactOnTestResult(org.apache.tools.ant.taskdefs.optional.junit.JUnitTask$TestResultHolder result, JUnitTest test, java.lang.String name)
Logs information about failed tests, potentially stops processing (by throwing a BuildException) if a failure/error occurred or sets a property.

param
result the result of the test.
param
test the test in question.
param
name the name of the test.
since
Ant 1.7

        // if there is an error/failure and that it should halt, stop
        // everything otherwise just log a statement
        boolean fatal = result.timedOut || result.crashed;
        boolean errorOccurredHere =
            result.exitCode == JUnitTaskMirror.JUnitTestRunnerMirror.ERRORS || fatal;
        boolean failureOccurredHere =
            result.exitCode != JUnitTaskMirror.JUnitTestRunnerMirror.SUCCESS || fatal;
        if (errorOccurredHere || failureOccurredHere) {
            if ((errorOccurredHere && test.getHaltonerror())
                || (failureOccurredHere && test.getHaltonfailure())) {
                throw new BuildException(name + " failed"
                    + (result.timedOut ? " (timeout)" : "")
                    + (result.crashed ? " (crashed)" : ""), getLocation());
            } else {
                log(name + " FAILED"
                    + (result.timedOut ? " (timeout)" : "")
                    + (result.crashed ? " (crashed)" : ""), Project.MSG_ERR);
                if (errorOccurredHere && test.getErrorProperty() != null) {
                    getProject().setNewProperty(test.getErrorProperty(), "true");
                }
                if (failureOccurredHere && test.getFailureProperty() != null) {
                    getProject().setNewProperty(test.getFailureProperty(), "true");
                }
            }
        }
    
public voidaddAssertions(org.apache.tools.ant.types.Assertions asserts)
Assertions to enable in this program (if fork=true)

since
Ant 1.6
param
asserts assertion set

        if (getCommandline().getAssertions() != null) {
            throw new BuildException("Only one assertion declaration is allowed");
        }
        getCommandline().setAssertions(asserts);
    
protected booleanaddClasspathEntry(java.lang.String resource)
Search for the given resource and add the directory or archive that contains it to the classpath.

Doesn't work for archives in JDK 1.1 as the URL returned by getResource doesn't contain the name of the archive.

param
resource resource that one wants to lookup
return
true if something was in fact added
since
Ant 1.4

        /*
         * pre Ant 1.6 this method used to call getClass().getResource
         * while Ant 1.6 will call ClassLoader.getResource().
         *
         * The difference is that Class.getResource expects a leading
         * slash for "absolute" resources and will strip it before
         * delegating to ClassLoader.getResource - so we now have to
         * emulate Class's behavior.
         */
        if (resource.startsWith("/")) {
            resource = resource.substring(1);
        } else {
            resource = "org/apache/tools/ant/taskdefs/optional/junit/"
                + resource;
        }

        File f = LoaderUtils.getResourceSource(getClass().getClassLoader(),
                                               resource);
        if (f != null) {
            log("Found " + f.getAbsolutePath(), Project.MSG_DEBUG);
            antRuntimeClasses.createPath().setLocation(f);
            return true;
        } else {
            log("Couldn\'t find " + resource, Project.MSG_DEBUG);
            return false;
        }
    
public voidaddConfiguredSysproperty(Environment.Variable sysp)
Adds a system property that tests can access. This might be useful to tranfer Ant properties to the testcases when JVM forking is not enabled.

param
sysp new environment variable to add
since
Ant 1.6

        // get a build exception if there is a missing key or value
        // see bugzilla report 21684
        String testString = sysp.getContent();
        getProject().log("sysproperty added : " + testString, Project.MSG_DEBUG);
        getCommandline().addSysproperty(sysp);
    
public voidaddEnv(Environment.Variable var)
Adds an environment variable; used when forking.

Will be ignored if we are not forking a new VM.

param
var environment variable to be added
since
Ant 1.5

        env.addVariable(var);
    
public voidaddFormatter(FormatterElement fe)
Add a new formatter to all tests of this task.

param
fe formatter element
since
Ant 1.2

        formatters.addElement(fe);
    
public voidaddSysproperty(Environment.Variable sysp)
Adds a system property that tests can access. This might be useful to tranfer Ant properties to the testcases when JVM forking is not enabled.

since
Ant 1.3
deprecated
since ant 1.6
param
sysp environment variable to add


        getCommandline().addSysproperty(sysp);
    
public voidaddSyspropertyset(org.apache.tools.ant.types.PropertySet sysp)
Adds a set of properties that will be used as system properties that tests can access. This might be useful to tranfer Ant properties to the testcases when JVM forking is not enabled.

param
sysp set of properties to be added
since
Ant 1.6

        getCommandline().addSyspropertyset(sysp);
    
public voidaddTest(JUnitTest test)
Add a new single testcase.

param
test a new single testcase
see
JUnitTest
since
Ant 1.2

        tests.addElement(test);
        preConfigure(test);
    
protected java.util.EnumerationallTests()
return an enumeration listing each test, then each batchtest

return
enumeration
since
Ant 1.3

        Enumeration[] enums = {tests.elements(), batchTests.elements()};
        return Enumerations.fromCompound(enums);
    
public BatchTestcreateBatchTest()
Adds a set of tests based on pattern matching.

return
a new instance of a batch test.
see
BatchTest
since
Ant 1.2

        BatchTest test = new BatchTest(getProject());
        batchTests.addElement(test);
        preConfigure(test);
        return test;
    
public org.apache.tools.ant.types.PathcreateBootclasspath()
Adds a path to the bootclasspath.

return
reference to the bootclasspath in the embedded java command line
since
Ant 1.6

        return getCommandline().createBootclasspath(getProject()).createPath();
    
private voidcreateClassLoader()
Creates and configures an AntClassLoader instance from the nested classpath element.

since
Ant 1.6

        Path userClasspath = getCommandline().getClasspath();
        if (userClasspath != null) {
            if (reloading || classLoader == null) {
                deleteClassLoader();
                Path classpath = (Path) userClasspath.clone();
                if (includeAntRuntime) {
                    log("Implicitly adding " + antRuntimeClasses
                        + " to CLASSPATH", Project.MSG_VERBOSE);
                    classpath.append(antRuntimeClasses);
                }
                classLoader = getProject().createClassLoader(classpath);
                if (getClass().getClassLoader() != null
                    && getClass().getClassLoader() != Project.class.getClassLoader()) {
                    classLoader.setParent(getClass().getClassLoader());
                }
                classLoader.setParentFirst(false);
                classLoader.addJavaLibraries();
                log("Using CLASSPATH " + classLoader.getClasspath(),
                    Project.MSG_VERBOSE);
                // make sure the test will be accepted as a TestCase
                classLoader.addSystemPackageRoot("junit");
                // make sure the test annotation are accepted
                classLoader.addSystemPackageRoot("org.junit");
                // will cause trouble in JDK 1.1 if omitted
                classLoader.addSystemPackageRoot("org.apache.tools.ant");
            }
        }
    
public org.apache.tools.ant.types.PathcreateClasspath()
Adds path to classpath used for tests.

return
reference to the classpath in the embedded java command line
since
Ant 1.2

        return getCommandline().createClasspath(getProject()).createPath();
    
public Commandline.ArgumentcreateJvmarg()
Adds a JVM argument; ignored if not forking.

return
create a new JVM argument so that any argument can be passed to the JVM.
see
#setFork(boolean)
since
Ant 1.2

        return getCommandline().createVmArgument();
    
private static JUnitTaskMirrorcreateMirror(org.apache.tools.ant.taskdefs.optional.junit.JUnitTask task, java.lang.ClassLoader loader)

        try {
            loader.loadClass("junit.framework.Test"); // sanity check
        } catch (ClassNotFoundException e) {
            throw new BuildException(
                    "The <classpath> for <junit> must include junit.jar "
                    + "if not in Ant's own classpath",
                    e, task.getLocation());
        }
        try {
            Class c = loader.loadClass(JUnitTaskMirror.class.getName() + "Impl");
            if (c.getClassLoader() != loader) {
                throw new BuildException("Overdelegating loader", task.getLocation());
            }
            Constructor cons = c.getConstructor(new Class[] {JUnitTask.class});
            return (JUnitTaskMirror) cons.newInstance(new Object[] {task});
        } catch (Exception e) {
            throw new BuildException(e, task.getLocation());
        }
    
public org.apache.tools.ant.types.PermissionscreatePermissions()
Sets the permissions for the application run inside the same JVM.

since
Ant 1.6
return
.

        if (perm == null) {
            perm = new Permissions();
        }
        return perm;
    
private java.io.FilecreateTempPropertiesFile(java.lang.String prefix)
Create a temporary file to pass the properties to a new process. Will auto-delete on (graceful) exit. The file will be in the project basedir unless tmpDir declares something else.

param
prefix
return
created file

        File propsFile =
            FILE_UTILS.createTempFile(prefix, ".properties",
                tmpDir != null ? tmpDir : getProject().getBaseDir(), true);
        return propsFile;
    
protected org.apache.tools.ant.taskdefs.ExecuteWatchdogcreateWatchdog()

return
null if there is a timeout value, otherwise the watchdog instance.
throws
BuildException under unspecified circumstances
since
Ant 1.2

        if (timeout == null) {
            return null;
        }
        return new ExecuteWatchdog((long) timeout.intValue());
    
private voiddeleteClassLoader()
Removes a classloader if needed.

since
Ant 1.7

        if (classLoader != null) {
            classLoader.cleanup();
            classLoader = null;
        }
    
public voidexecute()
Runs the testcase.

throws
BuildException in case of test failures or errors
since
Ant 1.2

        ClassLoader myLoader = JUnitTask.class.getClassLoader();
        ClassLoader mirrorLoader;
        if (splitJunit) {
            Path path = new Path(getProject());
            path.add(antRuntimeClasses);
            path.add(getCommandline().getClasspath());
            mirrorLoader = new SplitLoader(myLoader, path);
        } else {
            mirrorLoader = myLoader;
        }
        delegate = createMirror(this, mirrorLoader);

        List testLists = new ArrayList();

        boolean forkPerTest = forkMode.getValue().equals(ForkMode.PER_TEST);
        if (forkPerTest || forkMode.getValue().equals(ForkMode.ONCE)) {
            testLists.addAll(executeOrQueue(getIndividualTests(),
                                            forkPerTest));
        } else { /* forkMode.getValue().equals(ForkMode.PER_BATCH) */
            final int count = batchTests.size();
            for (int i = 0; i < count; i++) {
                BatchTest batchtest = (BatchTest) batchTests.elementAt(i);
                testLists.addAll(executeOrQueue(batchtest.elements(), false));
            }
            testLists.addAll(executeOrQueue(tests.elements(), forkPerTest));
        }

        try {
            Iterator iter = testLists.iterator();
            while (iter.hasNext()) {
                List l = (List) iter.next();
                if (l.size() == 1) {
                    execute((JUnitTest) l.get(0));
                } else {
                    execute(l);
                }
            }
        } finally {
            deleteClassLoader();
            if (mirrorLoader instanceof SplitLoader) {
                ((SplitLoader) mirrorLoader).cleanup();
            }
            delegate = null;
        }
    
protected voidexecute(JUnitTest arg)
Run the tests.

param
arg one JunitTest
throws
BuildException in case of test failures or errors

        JUnitTest test = (JUnitTest) arg.clone();
        // set the default values if not specified
        //@todo should be moved to the test class instead.
        if (test.getTodir() == null) {
            test.setTodir(getProject().resolveFile("."));
        }

        if (test.getOutfile() == null) {
            test.setOutfile("TEST-" + test.getName());
        }

        // execute the test and get the return code
        TestResultHolder result = null;
        if (!test.getFork()) {
            result = executeInVM(test);
        } else {
            ExecuteWatchdog watchdog = createWatchdog();
            result = executeAsForked(test, watchdog, null);
            // null watchdog means no timeout, you'd better not check with null
        }
        actOnTestResult(result, test, "Test " + test.getName());
    
protected voidexecute(java.util.List tests)
Execute a list of tests in a single forked Java VM.

param
tests the list of tests to execute.
throws
BuildException on error.

        JUnitTest test = null;
        // Create a temporary file to pass the test cases to run to
        // the runner (one test case per line)
        File casesFile = createTempPropertiesFile("junittestcases");
        PrintWriter writer = null;
        try {
            writer =
                new PrintWriter(new BufferedWriter(new FileWriter(casesFile)));
            Iterator iter = tests.iterator();
            while (iter.hasNext()) {
                test = (JUnitTest) iter.next();
                writer.print(test.getName());
                if (test.getTodir() == null) {
                    writer.print("," + getProject().resolveFile("."));
                } else {
                    writer.print("," + test.getTodir());
                }

                if (test.getOutfile() == null) {
                    writer.println("," + "TEST-" + test.getName());
                } else {
                    writer.println("," + test.getOutfile());
                }
            }
            writer.flush();
            writer.close();
            writer = null;

            // execute the test and get the return code
            ExecuteWatchdog watchdog = createWatchdog();
            TestResultHolder result =
                executeAsForked(test, watchdog, casesFile);
            actOnTestResult(result, test, "Tests");
        } catch (IOException e) {
            log(e.toString(), Project.MSG_ERR);
            throw new BuildException(e);
        } finally {
            if (writer != null) {
                writer.close();
            }

            try {
                casesFile.delete();
            } catch (Exception e) {
                log(e.toString(), Project.MSG_ERR);
            }
        }
    
private org.apache.tools.ant.taskdefs.optional.junit.JUnitTask$TestResultHolderexecuteAsForked(JUnitTest test, org.apache.tools.ant.taskdefs.ExecuteWatchdog watchdog, java.io.File casesFile)
Execute a testcase by forking a new JVM. The command will block until it finishes. To know if the process was destroyed or not or whether the forked Java VM exited abnormally, use the attributes of the returned holder object.

param
test the testcase to execute.
param
watchdog the watchdog in charge of cancelling the test if it exceeds a certain amount of time. Can be null, in this case the test could probably hang forever.
param
casesFile list of test cases to execute. Can be null, in this case only one test is executed.
throws
BuildException in case of error creating a temporary property file, or if the junit process can not be forked


        if (perm != null) {
            log("Permissions ignored when running in forked mode!",
                Project.MSG_WARN);
        }

        CommandlineJava cmd = null;
        try {
            cmd = (CommandlineJava) (getCommandline().clone());
        } catch (CloneNotSupportedException e) {
            throw new BuildException("This shouldn't happen", e, getLocation());
        }
        cmd.setClassname("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner");
        if (casesFile == null) {
            cmd.createArgument().setValue(test.getName());
        } else {
            log("Running multiple tests in the same VM", Project.MSG_VERBOSE);
            cmd.createArgument().setValue(Constants.TESTSFILE + casesFile);
        }

        cmd.createArgument().setValue(Constants.FILTERTRACE + test.getFiltertrace());
        cmd.createArgument().setValue(Constants.HALT_ON_ERROR + test.getHaltonerror());
        cmd.createArgument().setValue(Constants.HALT_ON_FAILURE
                                      + test.getHaltonfailure());
        if (includeAntRuntime) {
            Vector v = Execute.getProcEnvironment();
            Enumeration e = v.elements();
            while (e.hasMoreElements()) {
                String s = (String) e.nextElement();
                if (s.startsWith(CLASSPATH)) {
                    cmd.createClasspath(getProject()).createPath()
                        .append(new Path(getProject(),
                                         s.substring(CLASSPATH.length()
                                                     )));
                }
            }
            log("Implicitly adding " + antRuntimeClasses + " to CLASSPATH",
                Project.MSG_VERBOSE);
            cmd.createClasspath(getProject()).createPath()
                .append(antRuntimeClasses);
        }

        if (summary) {
            String prefix = "";
            if ("withoutanderr".equalsIgnoreCase(summaryValue)) {
                prefix = "OutErr";
            }
            cmd.createArgument()
                .setValue(Constants.FORMATTER
                          + "org.apache.tools.ant.taskdefs.optional.junit."
                          + prefix + "SummaryJUnitResultFormatter");
        }

        cmd.createArgument().setValue(Constants.SHOWOUTPUT
                                      + String.valueOf(showOutput));
        cmd.createArgument().setValue(Constants.OUTPUT_TO_FORMATTERS
                                      + String.valueOf(outputToFormatters));

        cmd.createArgument().setValue(
            Constants.LOGTESTLISTENEREVENTS + "true"); // #31885

        StringBuffer formatterArg = new StringBuffer(STRING_BUFFER_SIZE);
        final FormatterElement[] feArray = mergeFormatters(test);
        for (int i = 0; i < feArray.length; i++) {
            FormatterElement fe = feArray[i];
            if (fe.shouldUse(this)) {
                formatterArg.append(Constants.FORMATTER);
                formatterArg.append(fe.getClassname());
                File outFile = getOutput(fe, test);
                if (outFile != null) {
                    formatterArg.append(",");
                    formatterArg.append(outFile);
                }
                cmd.createArgument().setValue(formatterArg.toString());
                formatterArg = new StringBuffer();
            }
        }

        File vmWatcher = createTempPropertiesFile("junitvmwatcher");
        cmd.createArgument().setValue(Constants.CRASHFILE
                                      + vmWatcher.getAbsolutePath());
        File propsFile = createTempPropertiesFile("junit");
        cmd.createArgument().setValue(Constants.PROPSFILE
                                      + propsFile.getAbsolutePath());
        Hashtable p = getProject().getProperties();
        Properties props = new Properties();
        for (Enumeration e = p.keys(); e.hasMoreElements();) {
            Object key = e.nextElement();
            props.put(key, p.get(key));
        }
        try {
            FileOutputStream outstream = new FileOutputStream(propsFile);
            props.store(outstream, "Ant JUnitTask generated properties file");
            outstream.close();
        } catch (java.io.IOException e) {
            propsFile.delete();
            throw new BuildException("Error creating temporary properties "
                                     + "file.", e, getLocation());
        }

        Execute execute = new Execute(
            new JUnitLogStreamHandler(
                this,
                Project.MSG_INFO,
                Project.MSG_WARN),
            watchdog);
        execute.setCommandline(cmd.getCommandline());
        execute.setAntRun(getProject());
        if (dir != null) {
            execute.setWorkingDirectory(dir);
        }

        String[] environment = env.getVariables();
        if (environment != null) {
            for (int i = 0; i < environment.length; i++) {
                log("Setting environment variable: " + environment[i],
                    Project.MSG_VERBOSE);
            }
        }
        execute.setNewenvironment(newEnvironment);
        execute.setEnvironment(environment);

        log(cmd.describeCommand(), Project.MSG_VERBOSE);
        TestResultHolder result = new TestResultHolder();
        try {
            result.exitCode = execute.execute();
        } catch (IOException e) {
            throw new BuildException("Process fork failed.", e, getLocation());
        } finally {
            String vmCrashString = "unknown";
            BufferedReader br = null;
            try {
                br = new BufferedReader(new FileReader(vmWatcher));
                vmCrashString = br.readLine();
            } catch (Exception e) {
                e.printStackTrace();
                // ignored.
            } finally {
                FileUtils.close(br);
            }
            if (watchdog != null && watchdog.killedProcess()) {
                result.timedOut = true;
                logTimeout(feArray, test, vmCrashString);
            } else if (!Constants.TERMINATED_SUCCESSFULLY.equals(vmCrashString)) {
                result.crashed = true;
                logVmCrash(feArray, test, vmCrashString);
            }
            vmWatcher.delete();

            if (!propsFile.delete()) {
                throw new BuildException("Could not delete temporary "
                                         + "properties file.");
            }
        }

        return result;
    
private org.apache.tools.ant.taskdefs.optional.junit.JUnitTask$TestResultHolderexecuteInVM(JUnitTest arg)
Execute inside VM.

param
arg one JUnitTest
throws
BuildException under unspecified circumstances

        JUnitTest test = (JUnitTest) arg.clone();
        test.setProperties(getProject().getProperties());
        if (dir != null) {
            log("dir attribute ignored if running in the same VM",
                Project.MSG_WARN);
        }

        if (newEnvironment || null != env.getVariables()) {
            log("Changes to environment variables are ignored if running in "
                + "the same VM.", Project.MSG_WARN);
        }

        if (getCommandline().getBootclasspath() != null) {
            log("bootclasspath is ignored if running in the same VM.",
                Project.MSG_WARN);
        }

        CommandlineJava.SysProperties sysProperties =
                getCommandline().getSystemProperties();
        if (sysProperties != null) {
            sysProperties.setSystem();
        }

        try {
            log("Using System properties " + System.getProperties(),
                Project.MSG_VERBOSE);
            if (splitJunit) {
                classLoader = (AntClassLoader) delegate.getClass().getClassLoader();
            } else {
                createClassLoader();
            }
            if (classLoader != null) {
                classLoader.setThreadContextLoader();
            }
            runner = delegate.newJUnitTestRunner(test, test.getHaltonerror(),
                                         test.getFiltertrace(),
                                         test.getHaltonfailure(), false,
                                         true, classLoader);
            if (summary) {

                JUnitTaskMirror.SummaryJUnitResultFormatterMirror f =
                    delegate.newSummaryJUnitResultFormatter();
                f.setWithOutAndErr("withoutanderr"
                                   .equalsIgnoreCase(summaryValue));
                f.setOutput(getDefaultOutput());
                runner.addFormatter(f);
            }

            runner.setPermissions(perm);

            final FormatterElement[] feArray = mergeFormatters(test);
            for (int i = 0; i < feArray.length; i++) {
                FormatterElement fe = feArray[i];
                if (fe.shouldUse(this)) {
                    File outFile = getOutput(fe, test);
                    if (outFile != null) {
                        fe.setOutfile(outFile);
                    } else {
                        fe.setOutput(getDefaultOutput());
                    }
                    runner.addFormatter(fe.createFormatter(classLoader));
                }
            }

            runner.run();
            TestResultHolder result = new TestResultHolder();
            result.exitCode = runner.getRetCode();
            return result;
        } finally {
            if (sysProperties != null) {
                sysProperties.restoreSystem();
            }
            if (classLoader != null) {
                classLoader.resetThreadContextLoader();
            }
        }
    
protected java.util.CollectionexecuteOrQueue(java.util.Enumeration testList, boolean runIndividual)
Executes all tests that don't need to be forked (or all tests if the runIndividual argument is true. Returns a collection of lists of tests that share the same VM configuration and haven't been executed yet.

param
testList the list of tests to be executed or queued.
param
runIndividual if true execute each test individually.
return
a list of tasks to be executed.
since
1.6.2

        Map testConfigurations = new HashMap();
        while (testList.hasMoreElements()) {
            JUnitTest test = (JUnitTest) testList.nextElement();
            if (test.shouldRun(getProject())) {
                if (runIndividual || !test.getFork()) {
                    execute(test);
                } else {
                    ForkedTestConfiguration c =
                        new ForkedTestConfiguration(test);
                    List l = (List) testConfigurations.get(c);
                    if (l == null) {
                        l = new ArrayList();
                        testConfigurations.put(c, l);
                    }
                    l.add(test);
                }
            }
        }
        return testConfigurations.values();
    
protected org.apache.tools.ant.types.CommandlineJavagetCommandline()
Get the command line used to run the tests.

return
the command line.
since
Ant 1.6.2

        if (commandline == null) {
            commandline = new CommandlineJava();
        }
        return commandline;
    
protected java.io.OutputStreamgetDefaultOutput()
Get the default output for a formatter.

return
default output stream for a formatter
since
Ant 1.3

        return new LogOutputStream(this, Project.MSG_INFO);
    
protected java.util.EnumerationgetIndividualTests()
Merge all individual tests from the batchtest with all individual tests and return an enumeration over all JUnitTest.

return
enumeration over individual tests
since
Ant 1.3

        final int count = batchTests.size();
        final Enumeration[] enums = new Enumeration[ count + 1];
        for (int i = 0; i < count; i++) {
            BatchTest batchtest = (BatchTest) batchTests.elementAt(i);
            enums[i] = batchtest.elements();
        }
        enums[enums.length - 1] = tests.elements();
        return Enumerations.fromCompound(enums);
    
protected java.io.FilegetOutput(FormatterElement fe, JUnitTest test)
If the formatter sends output to a file, return that file. null otherwise.

param
fe formatter element
param
test one JUnit test
return
file reference
since
Ant 1.3

        if (fe.getUseFile()) {
            String base = test.getOutfile();
            if (base == null) {
                base = JUnitTaskMirror.JUnitTestRunnerMirror.IGNORED_FILE_NAME;
            }
            String filename = base + fe.getExtension();
            File destFile = new File(test.getTodir(), filename);
            String absFilename = destFile.getAbsolutePath();
            return getProject().resolveFile(absFilename);
        }
        return null;
    
public voidhandleErrorFlush(java.lang.String output)
Pass output sent to System.err to the TestRunner so it can collect it for the formatters.

param
output coming from System.err
since
Ant 1.5.2

        if (runner != null) {
            runner.handleErrorFlush(output);
            if (showOutput) {
                super.handleErrorFlush(output);
            }
        } else {
            super.handleErrorFlush(output);
        }
    
public voidhandleErrorOutput(java.lang.String output)
Pass output sent to System.err to the TestRunner so it can collect it for the formatters.

param
output output coming from System.err
since
Ant 1.5

        if (runner != null) {
            runner.handleErrorOutput(output);
            if (showOutput) {
                super.handleErrorOutput(output);
            }
        } else {
            super.handleErrorOutput(output);
        }
    
protected voidhandleFlush(java.lang.String output)
Pass output sent to System.out to the TestRunner so it can collect ot for the formatters.

param
output output coming from System.out
since
Ant 1.5.2

        if (runner != null) {
            runner.handleFlush(output);
            if (showOutput) {
                super.handleFlush(output);
            }
        } else {
            super.handleFlush(output);
        }
    
protected inthandleInput(byte[] buffer, int offset, int length)
Handle an input request by this task.

see
Task#handleInput(byte[], int, int) This implementation delegates to a runner if it present.
param
buffer the buffer into which data is to be read.
param
offset the offset into the buffer at which data is stored.
param
length the amount of data to read.
return
the number of bytes read.
exception
IOException if the data cannot be read.
since
Ant 1.6

        if (runner != null) {
            return runner.handleInput(buffer, offset, length);
        } else {
            return super.handleInput(buffer, offset, length);
        }
    
protected voidhandleOutput(java.lang.String output)
Pass output sent to System.out to the TestRunner so it can collect ot for the formatters.

param
output output coming from System.out
since
Ant 1.5

        if (output.startsWith(TESTLISTENER_PREFIX)) {
            log(output, Project.MSG_VERBOSE);
        } else if (runner != null) {
            if (outputToFormatters) {
                runner.handleOutput(output);
            }
            if (showOutput) {
                super.handleOutput(output);
            }
        } else {
            super.handleOutput(output);
        }
    
public voidinit()
Adds the jars or directories containing Ant, this task and JUnit to the classpath - this should make the forked JVM work without having to specify them directly.

since
Ant 1.4

        antRuntimeClasses = new Path(getProject());
        splitJunit = !addClasspathEntry("/junit/framework/TestCase.class");
        addClasspathEntry("/org/apache/tools/ant/launch/AntMain.class");
        addClasspathEntry("/org/apache/tools/ant/Task.class");
        addClasspathEntry("/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.class");
    
private voidlogTimeout(FormatterElement[] feArray, JUnitTest test, java.lang.String testCase)
Take care that some output is produced in report files if the watchdog kills the test.

since
Ant 1.5.2

        logVmExit(
            feArray, test,
            "Timeout occurred. Please note the time in the report does"
            + " not reflect the time until the timeout.",
            testCase);
    
private voidlogVmCrash(FormatterElement[] feArray, JUnitTest test, java.lang.String testCase)
Take care that some output is produced in report files if the forked machine exited before the test suite finished but the reason is not a timeout.

since
Ant 1.7

        logVmExit(
            feArray, test,
            "Forked Java VM exited abnormally. Please note the time in the report"
            + " does not reflect the time until the VM exit.",
            testCase);
    
private voidlogVmExit(FormatterElement[] feArray, JUnitTest test, java.lang.String message, java.lang.String testCase)
Take care that some output is produced in report files if the forked machine terminated before the test suite finished

since
Ant 1.7

        try {
            log("Using System properties " + System.getProperties(),
                Project.MSG_VERBOSE);
            if (splitJunit) {
                classLoader = (AntClassLoader) delegate.getClass().getClassLoader();
            } else {
                createClassLoader();
            }
            if (classLoader != null) {
                classLoader.setThreadContextLoader();
            }

            test.setCounts(1, 0, 1);
            test.setProperties(getProject().getProperties());
            for (int i = 0; i < feArray.length; i++) {
                FormatterElement fe = feArray[i];
                File outFile = getOutput(fe, test);
                JUnitTaskMirror.JUnitResultFormatterMirror formatter =
                    fe.createFormatter(classLoader);
                if (outFile != null && formatter != null) {
                    try {
                        OutputStream out = new FileOutputStream(outFile);
                        delegate.addVmExit(test, formatter, out, message, testCase);
                    } catch (IOException e) {
                        // ignore
                    }
                }
            }
            if (summary) {
                JUnitTaskMirror.SummaryJUnitResultFormatterMirror f =
                    delegate.newSummaryJUnitResultFormatter();
                f.setWithOutAndErr("withoutanderr".equalsIgnoreCase(summaryValue));
                delegate.addVmExit(test, f, getDefaultOutput(), message, testCase);
            }
        } finally {
            if (classLoader != null) {
                classLoader.resetThreadContextLoader();
            }
        }
    
private FormatterElement[]mergeFormatters(JUnitTest test)

param
test junit test
return
array of FormatterElement
since
Ant 1.3

        Vector feVector = (Vector) formatters.clone();
        test.addFormattersTo(feVector);
        FormatterElement[] feArray = new FormatterElement[feVector.size()];
        feVector.copyInto(feArray);
        return feArray;
    
private voidpreConfigure(BaseTest test)
Preset the attributes of the test before configuration in the build script. This allows attributes in the task be be defaults for the tests, but allows individual tests to override the defaults.

        test.setFiltertrace(filterTrace);
        test.setHaltonerror(haltOnError);
        if (errorProperty != null) {
            test.setErrorProperty(errorProperty);
        }
        test.setHaltonfailure(haltOnFail);
        if (failureProperty != null) {
            test.setFailureProperty(failureProperty);
        }
        test.setFork(fork);
    
public voidsetCloneVm(boolean cloneVm)
If set, system properties will be copied to the cloned VM - as well as the bootclasspath unless you have explicitly specified a bootclaspath.

Doesn't have any effect unless fork is true.

param
cloneVm a boolean value.
since
Ant 1.7

        getCommandline().setCloneVm(cloneVm);
    
public voidsetDir(java.io.File dir)
The directory to invoke the VM in. Ignored if no JVM is forked.

param
dir the directory to invoke the JVM from.
see
#setFork(boolean)
since
Ant 1.2

        this.dir = dir;
    
public voidsetErrorProperty(java.lang.String propertyName)
Property to set to "true" if there is a error in a test.

This property is applied on all BatchTest (batchtest) and JUnitTest (test), however, it can possibly be overriden by their own properties.

param
propertyName the name of the property to set in the event of an error.
since
Ant 1.4

        this.errorProperty = propertyName;
    
public voidsetFailureProperty(java.lang.String propertyName)
Property to set to "true" if there is a failure in a test.

This property is applied on all BatchTest (batchtest) and JUnitTest (test), however, it can possibly be overriden by their own properties.

param
propertyName the name of the property to set in the event of an failure.
since
Ant 1.4

        this.failureProperty = propertyName;
    
public voidsetFiltertrace(boolean value)
If true, smartly filter the stack frames of JUnit errors and failures before reporting them.

This property is applied on all BatchTest (batchtest) and JUnitTest (test) however it can possibly be overridden by their own properties.

param
value false if it should not filter, otherwise true
since
Ant 1.5

        this.filterTrace = value;
    
public voidsetFork(boolean value)
If true, JVM should be forked for each test.

It avoids interference between testcases and possibly avoids hanging the build. this property is applied on all BatchTest (batchtest) and JUnitTest (test) however it can possibly be overridden by their own properties.

param
value true if a JVM should be forked, otherwise false
see
#setTimeout
since
Ant 1.2

        this.fork = value;
    
public voidsetForkMode(org.apache.tools.ant.taskdefs.optional.junit.JUnitTask$ForkMode mode)
Set the behavior when {@link #setFork fork} fork has been enabled.

Possible values are "once", "perTest" and "perBatch". If set to "once", only a single Java VM will be forked for all tests, with "perTest" (the default) each test will run in a fresh Java VM and "perBatch" will run all tests from the same <batchtest> in the same Java VM.

This attribute will be ignored if tests run in the same VM as Ant.

Only tests with the same configuration of haltonerror, haltonfailure, errorproperty, failureproperty and filtertrace can share a forked Java VM, so even if you set the value to "once", Ant may need to fork mutliple VMs.

param
mode the mode to use.
since
Ant 1.6.2

        this.forkMode = mode;
    
public voidsetHaltonerror(boolean value)
If true, stop the build process when there is an error in a test. This property is applied on all BatchTest (batchtest) and JUnitTest (test) however it can possibly be overridden by their own properties.

param
value true if it should halt, otherwise false
since
Ant 1.2

        this.haltOnError = value;
    
public voidsetHaltonfailure(boolean value)
If true, stop the build process if a test fails (errors are considered failures as well). This property is applied on all BatchTest (batchtest) and JUnitTest (test) however it can possibly be overridden by their own properties.

param
value true if it should halt, otherwise false
since
Ant 1.2

        this.haltOnFail = value;
    
public voidsetIncludeantruntime(boolean b)
If true, include ant.jar, optional.jar and junit.jar in the forked VM.

param
b include ant run time yes or no
since
Ant 1.5

        includeAntRuntime = b;
    
public voidsetJvm(java.lang.String value)
The command used to invoke the Java Virtual Machine, default is 'java'. The command is resolved by java.lang.Runtime.exec(). Ignored if fork is disabled.

param
value the new VM to use instead of java
see
#setFork(boolean)
since
Ant 1.2

        getCommandline().setVm(value);
    
public voidsetMaxmemory(java.lang.String max)
Set the maximum memory to be used by all forked JVMs.

param
max the value as defined by -mx or -Xmx in the java command line options.
since
Ant 1.2

        getCommandline().setMaxmemory(max);
    
public voidsetNewenvironment(boolean newenv)
If true, use a new environment when forked.

Will be ignored if we are not forking a new VM.

param
newenv boolean indicating if setting a new environment is wished
since
Ant 1.5

        newEnvironment = newenv;
    
public voidsetOutputToFormatters(boolean outputToFormatters)
If true, send any output generated by tests to the formatters.

param
outputToFormatters if true, send output to formatters (Default is true).
since
Ant 1.7.0

        this.outputToFormatters = outputToFormatters;
    
public voidsetPrintsummary(org.apache.tools.ant.taskdefs.optional.junit.JUnitTask$SummaryAttribute value)
If true, print one-line statistics for each test, or "withOutAndErr" to also show standard output and error. Can take the values on, off, and withOutAndErr.

param
value true to print a summary, withOutAndErr to include the test's output as well, false otherwise.
see
SummaryJUnitResultFormatter
since
Ant 1.2

        summaryValue = value.getValue();
        summary = value.asBoolean();
    
public voidsetReloading(boolean value)
If true, force ant to re-classload all classes for each JUnit TestCase

param
value force class reloading for each test case


                              
        
        reloading = value;
    
public voidsetShowOutput(boolean showOutput)
If true, send any output generated by tests to Ant's logging system as well as to the formatters. By default only the formatters receive the output.

Output will always be passed to the formatters and not by shown by default. This option should for example be set for tests that are interactive and prompt the user to do something.

param
showOutput if true, send output to Ant's logging system too
since
Ant 1.5

        this.showOutput = showOutput;
    
public voidsetTempdir(java.io.File tmpDir)
Where Ant should place temporary files.

param
tmpDir location where temporary files should go to
since
Ant 1.6

        if (tmpDir != null) {
            if (!tmpDir.exists() || !tmpDir.isDirectory()) {
                throw new BuildException(tmpDir.toString()
                                         + " is not a valid temp directory");
            }
        }
        this.tmpDir = tmpDir;
    
public voidsetTimeout(java.lang.Integer value)
Set the timeout value (in milliseconds).

If the test is running for more than this value, the test will be canceled. (works only when in 'fork' mode).

param
value the maximum time (in milliseconds) allowed before declaring the test as 'timed-out'
see
#setFork(boolean)
since
Ant 1.2

        timeout = value;