Author: jglick
Date: Tue Feb 28 13:07:15 2006
New Revision: 381780
URL: http://svn.apache.org/viewcvs?rev=381780&view=rev
Log:
#38811: support for JUnit 4.0.
Modified:
ant/core/trunk/WHATSNEW
ant/core/trunk/docs/manual/OptionalTasks/junit.html
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitVersionHelper.java
Modified: ant/core/trunk/WHATSNEW
URL: http://svn.apache.org/viewcvs/ant/core/trunk/WHATSNEW?rev=381780&r1=381779&r2=381780&view=diff
==============================================================================
--- ant/core/trunk/WHATSNEW (original)
+++ ant/core/trunk/WHATSNEW Tue Feb 28 13:07:15 2006
@@ -77,6 +77,8 @@
Fixed bugs:
-----------
+* <junit> now supports JUnit 4. Bugzilla Report 38811.
+
* <junit> can now work with junit.jar in its <classpath>. Bugzilla Report 38799.
* Some potential NullPointerExceptions, Bugzilla Reports 37765 and 38056
Modified: ant/core/trunk/docs/manual/OptionalTasks/junit.html
URL: http://svn.apache.org/viewcvs/ant/core/trunk/docs/manual/OptionalTasks/junit.html?rev=381780&r1=381779&r2=381780&view=diff
==============================================================================
--- ant/core/trunk/docs/manual/OptionalTasks/junit.html (original)
+++ ant/core/trunk/docs/manual/OptionalTasks/junit.html Tue Feb 28 13:07:15 2006
@@ -12,7 +12,8 @@
version of the framework can be found at
<a href="http://www.junit.org">http://www.junit.org</a>.
This task has been tested with JUnit 3.0 up to JUnit 3.8.1; it won't
-work with versions prior to JUnit 3.0.</p>
+work with versions prior to JUnit 3.0. It also works with JUnit 4.0, including
+"pure" JUnit 4 tests using only annotations and no <code>JUnit4TestAdapter</code>.</p>
<p><strong>Note:</strong> This task depends on external libraries not included
in the Ant distribution. See <a href="../install.html#librarydependencies">
Library Dependencies</a> for more information.
Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java?rev=381780&r1=381779&r2=381780&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
(original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
Tue Feb 28 13:07:15 2006
@@ -35,6 +35,7 @@
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 @@
"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 @@
/** 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 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 @@
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 @@
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 @@
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 @@
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 @@
}
}
}
+
+ /**
+ * 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
Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitVersionHelper.java
URL: http://svn.apache.org/viewcvs/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitVersionHelper.java?rev=381780&r1=381779&r2=381780&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitVersionHelper.java
(original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitVersionHelper.java
Tue Feb 28 13:07:15 2006
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2002,2004-2005 The Apache Software Foundation
+ * Copyright 2001-2002,2004-2006 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,8 +51,21 @@
* <p>since Ant 1.5.1 this method will invoke "<code>public
* String getName()</code>" on any implementation of Test if
* it exists.</p>
+ *
+ * <p>Since Ant 1.7 also checks for JUnit4TestCaseFacade explicitly.
+ * This is used by junit.framework.JUnit4TestAdapter.</p>
*/
public static String getTestCaseName(Test t) {
+ if (t != null && t.getClass().getName().equals("junit.framework.JUnit4TestCaseFacade"))
{
+ // Self-describing as of JUnit 4 (#38811). But trim "(ClassName)".
+ String name = t.toString();
+ if (name.endsWith(")")) {
+ int paren = name.lastIndexOf('(');
+ return name.substring(0, paren);
+ } else {
+ return name;
+ }
+ }
if (t instanceof TestCase && testCaseName != null) {
try {
return (String) testCaseName.invoke(t, new Object[0]);
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org
|