|
|
@@ -35,6 +35,7 @@ import java.util.StringTokenizer; |
|
|
|
import java.util.Vector; |
|
|
|
import junit.framework.AssertionFailedError; |
|
|
|
import junit.framework.Test; |
|
|
|
import junit.framework.TestFailure; |
|
|
|
import junit.framework.TestListener; |
|
|
|
import junit.framework.TestResult; |
|
|
|
import junit.framework.TestSuite; |
|
|
@@ -99,7 +100,13 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR |
|
|
|
"junit.textui.TestRunner", |
|
|
|
"java.lang.reflect.Method.invoke(", |
|
|
|
"sun.reflect.", |
|
|
|
"org.apache.tools.ant." |
|
|
|
"org.apache.tools.ant.", |
|
|
|
// JUnit 4 support: |
|
|
|
"org.junit.", |
|
|
|
"junit.framework.JUnit4TestAdapter", |
|
|
|
// See wrapListener for reason: |
|
|
|
"Caused by: java.lang.AssertionError", |
|
|
|
" more", |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@@ -141,6 +148,9 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR |
|
|
|
/** Do we print TestListener events? */ |
|
|
|
private boolean logTestListenerEvents = false; |
|
|
|
|
|
|
|
/** Turned on if we are using JUnit 4 for this test suite. see #38811 */ |
|
|
|
private boolean junit4; |
|
|
|
|
|
|
|
/** |
|
|
|
* Constructor for fork=true or when the user hasn't specified a |
|
|
|
* classpath. |
|
|
@@ -212,9 +222,9 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR |
|
|
|
|
|
|
|
public void run() { |
|
|
|
res = new TestResult(); |
|
|
|
res.addListener(this); |
|
|
|
res.addListener(wrapListener(this)); |
|
|
|
for (int i = 0; i < formatters.size(); i++) { |
|
|
|
res.addListener((TestListener) formatters.elementAt(i)); |
|
|
|
res.addListener(wrapListener((TestListener) formatters.elementAt(i))); |
|
|
|
} |
|
|
|
|
|
|
|
ByteArrayOutputStream errStrm = new ByteArrayOutputStream(); |
|
|
@@ -255,6 +265,19 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR |
|
|
|
try { |
|
|
|
|
|
|
|
try { |
|
|
|
Class junit4TestAdapterClass = null; |
|
|
|
// Note that checking for JDK 5 directly won't work; under JDK 4, this will already have failed. |
|
|
|
try { |
|
|
|
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; |
|
|
|
|
|
|
|
Class testClass = null; |
|
|
|
if (loader == null) { |
|
|
|
testClass = Class.forName(junitTest.getName()); |
|
|
@@ -263,24 +286,33 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR |
|
|
|
loader); |
|
|
|
} |
|
|
|
|
|
|
|
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]); |
|
|
|
if (junit4) { |
|
|
|
// Let's use it! |
|
|
|
suite = (Test) junit4TestAdapterClass.getConstructor(new Class[] {Class.class}). |
|
|
|
newInstance(new Object[] {testClass}); |
|
|
|
} else { |
|
|
|
// try to extract a test suite automatically this |
|
|
|
// will generate warnings if the class is no |
|
|
|
// suitable Test |
|
|
|
suite = new TestSuite(testClass); |
|
|
|
// Use JUnit 3. |
|
|
|
|
|
|
|
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 { |
|
|
|
// 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) { |
|
|
@@ -303,8 +335,13 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR |
|
|
|
logTestListenerEvent("tests to run: " + suite.countTestCases()); |
|
|
|
suite.run(res); |
|
|
|
} finally { |
|
|
|
junitTest.setCounts(res.runCount(), res.failureCount(), |
|
|
|
res.errorCount()); |
|
|
|
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); |
|
|
|
} |
|
|
|
} |
|
|
@@ -692,7 +729,7 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR |
|
|
|
|
|
|
|
private static boolean filterLine(String line) { |
|
|
|
for (int i = 0; i < DEFAULT_TRACE_FILTERS.length; i++) { |
|
|
|
if (line.indexOf(DEFAULT_TRACE_FILTERS[i]) > 0) { |
|
|
|
if (line.indexOf(DEFAULT_TRACE_FILTERS[i]) != -1) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
@@ -733,4 +770,83 @@ public class JUnitTestRunner implements TestListener, JUnitTaskMirror.JUnitTestR |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Modifies a TestListener when running JUnit 4: |
|
|
|
* treats AssertionFailedError as a failure not an error. |
|
|
|
* @since Ant 1.7 |
|
|
|
*/ |
|
|
|
private TestListener wrapListener(final TestListener testListener) { |
|
|
|
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); |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Use instead of TestResult.get{Failure,Error}Count on JUnit 4, |
|
|
|
* since the adapter claims that all failures are errors. |
|
|
|
* @since Ant 1.7 |
|
|
|
*/ |
|
|
|
private int[] findJUnit4FailureErrorCount(TestResult res) { |
|
|
|
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}; |
|
|
|
} |
|
|
|
|
|
|
|
} // JUnitTestRunner |