JUnitTestRunnerpublic class JUnitTestRunner extends Object implements JUnitTaskMirror.JUnitTestRunnerMirror, TestListenerSimple 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. |
Fields Summary |
---|
private Vector | formattersHolds the registered formatters. | private TestResult | resCollects TestResults. | private static boolean | filtertraceDo we filter junit.*.* stack frames out of failure and error exceptions. | private boolean | showOutputDo we send output to System.out/.err in addition to the formatters? | private boolean | outputToFormatters | private org.apache.tools.ant.types.Permissions | permThe permissions set for the test to run. | private static final String[] | DEFAULT_TRACE_FILTERS | private boolean | haltOnErrorDo we stop on errors. | private boolean | haltOnFailureDo we stop on test failures. | private int | retCodeReturncode | private JUnitTest | junitTestThe TestSuite we are currently running. | private PrintStream | systemErroroutput written during the test | private PrintStream | systemOutError output during the test | private boolean | forkedis this runner running in forked mode? | private static boolean | multipleTestsRunning more than one test suite? | private ClassLoader | loaderClassLoader passed in in non-forked mode. | private boolean | logTestListenerEventsDo we print TestListener events? | private boolean | junit4Turned on if we are using JUnit 4 for this test suite. see #38811 | private static String | crashFileThe 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.
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.
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.
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.
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.
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.
JUnitTestRunner.filtertrace = filtertrace;
this.junitTest = test;
this.haltOnError = haltOnError;
this.haltOnFailure = haltOnFailure;
this.showOutput = showOutput;
this.logTestListenerEvents = logTestListenerEvents;
this.loader = loader;
|
Methods Summary |
---|
public void | addError(junit.framework.Test test, java.lang.Throwable t)Interface TestListener.
An error occurred while running the test.
String testName = JUnitVersionHelper.getTestCaseName(test);
logTestListenerEvent("addError(" + testName + ", " + t.getMessage() + ")");
if (haltOnError) {
res.stop();
}
| public void | addFailure(junit.framework.Test test, java.lang.Throwable t)Interface TestListener for JUnit <= 3.4.
A Test failed.
String testName = JUnitVersionHelper.getTestCaseName(test);
logTestListenerEvent("addFailure(" + testName + ", " + t.getMessage() + ")");
if (haltOnFailure) {
res.stop();
}
| public void | addFailure(junit.framework.Test test, junit.framework.AssertionFailedError t)Interface TestListener for JUnit > 3.4.
A Test failed.
addFailure(test, (Throwable) t);
| public void | addFormatter(JUnitResultFormatter f)Add a formatter.
formatters.addElement(f);
| public void | addFormatter(JUnitTaskMirror.JUnitResultFormatterMirror f){@inheritDoc}.
formatters.addElement((JUnitResultFormatter) f);
| private static void | createAndStoreFormatter(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 void | endTest(junit.framework.Test test)Interface TestListener.
A Test is finished.
String testName = JUnitVersionHelper.getTestCaseName(test);
logTestListenerEvent("endTest(" + testName + ")");
| private static boolean | filterLine(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.String | filterStack(java.lang.String stack)Filters stack frames from internal JUnit and Ant classes
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.
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 void | fireEndTestSuite()
for (int i = 0; i < formatters.size(); i++) {
((JUnitResultFormatter) formatters.elementAt(i))
.endTestSuite(junitTest);
}
| private void | fireStartTestSuite()
for (int i = 0; i < formatters.size(); i++) {
((JUnitResultFormatter) formatters.elementAt(i))
.startTestSuite(junitTest);
}
| public static java.lang.String | getFilteredTrace(java.lang.Throwable t)Returns a filtered stack trace.
This is ripped out of junit.runner.BaseTestRunner.
String trace = StringUtils.getStackTrace(t);
return JUnitTestRunner.filterStack(trace);
| public int | getRetCode()Returns what System.exit() would return in the standalone version.
return retCode;
| public void | handleErrorFlush(java.lang.String output){@inheritDoc}.
if (systemError != null) {
systemError.print(output);
}
| public void | handleErrorOutput(java.lang.String output){@inheritDoc}.
if (systemError != null) {
systemError.print(output);
}
| public void | handleFlush(java.lang.String output){@inheritDoc}.
if (systemOut != null) {
systemOut.print(output);
}
| public int | handleInput(byte[] buffer, int offset, int length)Handle input.
return -1;
| public void | handleOutput(java.lang.String output)Handle a string destined for standard output.
if (!logTestListenerEvents && output.startsWith(JUnitTask.TESTLISTENER_PREFIX)) {
// ignore
} else if (systemOut != null) {
systemOut.print(output);
}
| private static int | launch(JUnitTest t, boolean haltError, boolean stackfilter, boolean haltFail, boolean showOut, boolean outputToFormat, boolean logTestListenerEvents, java.util.Properties props)
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 void | logTestListenerEvent(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 void | main(java.lang.String[] args)Entry point for standalone (forked) mode.
Parameters: testcaseclassname plus parameters in the format
key=value, none of which is required.
key | description | default value |
haltOnError | halt test on
errors? | false |
haltOnFailure | halt test on
failures? | false |
formatter | A JUnitResultFormatter given as
classname,filename. If filename is ommitted, System.out is
assumed. | none |
showoutput | send output to System.err/.out as
well as to the formatters? | false |
logtestlistenerevents | log TestListener events to
System.out. | false |
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 void | registerNonCrash()
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 void | registerTestCase(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 void | run()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 void | sendOutAndErr(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 void | setPermissions(org.apache.tools.ant.types.Permissions permissions)Permissions for the test run.
perm = permissions;
| public void | startTest(junit.framework.Test t)Interface TestListener.
A new Test is started.
String testName = JUnitVersionHelper.getTestCaseName(t);
logTestListenerEvent("startTest(" + testName + ")");
| private static void | transferFormatters(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.TestListener | wrapListener(junit.framework.TestListener testListener)Modifies a TestListener when running JUnit 4: treats AssertionFailedError
as a failure not an error.
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);
}
};
|
|