diff --git a/src/etc/testcases/taskdefs/optional/junit.xml b/src/etc/testcases/taskdefs/optional/junit.xml
index f01973b69..253df7a9f 100644
--- a/src/etc/testcases/taskdefs/optional/junit.xml
+++ b/src/etc/testcases/taskdefs/optional/junit.xml
@@ -143,4 +143,94 @@
+
+
Collects all failing test cases and creates a new JUnit test class containing + * a suite() method which calls these failed tests.
+ *Having classes A ... D with each several testcases you could earn a new + * test class like + *
+ * // generated on: 2007.08.06 09:42:34,555 + * import junit.framework.*; + * public class FailedTests extends TestCase { + * public FailedTests(String s) { + * super(s); + * } + * public static Test suite() { + * TestSuite suite = new TestSuite(); + * suite.addTest( new B("test04") ); + * suite.addTest( new org.D("test10") ); + * return suite; + * } + * } + *+ * + * @since Ant 1.7.1 + */ +/* + * Because each running test case gets its own formatter, we collect + * the failing test cases in a static list. Because we dont have a finalizer + * method in the formatters "lifecycle", we regenerate the new java source + * at each end of a test suite. The last run will contain all failed tests. + */ +public class FailureRecorder implements JUnitResultFormatter { + + /** + * This is the name of a magic System property ({@value}). The value of this + * System property should point to the location where to store the + * generated class (without suffix). + * Default location and name is defined in DEFAULT_CLASS_LOCATION. + * @see #DEFAULT_CLASS_LOCATION + */ + public static final String MAGIC_PROPERTY_CLASS_LOCATION = "ant.junit.failureCollector"; + + /** Default location and name for the generated JUnit class file. {@value} */ + public static final String DEFAULT_CLASS_LOCATION = System.getProperty("java.io.tmpdir") + "FailedTests"; + + /** Class names of failed tests without duplicates. */ + private static HashSet/*
Quick way to use a standard formatter. @@ -77,6 +81,7 @@ public class FormatterElement { *
xml
type uses a XMLJUnitResultFormatter
.
* brief
type uses a BriefJUnitResultFormatter
.
* plain
type (the default) uses a PlainJUnitResultFormatter
.
+ * failure
type uses a FailureRecorder
.
*
*
* Sets classname
attribute - so you can't use that
@@ -84,13 +89,18 @@ public class FormatterElement {
* @param type the enumerated value to use.
*/
public void setType(TypeAttribute type) {
+ //TODO: Besseren Zugriffsalgorithums: TypeAttribut.getClassname()
if ("xml".equals(type.getValue())) {
setClassname(XML_FORMATTER_CLASS_NAME);
} else {
if ("brief".equals(type.getValue())) {
setClassname(BRIEF_FORMATTER_CLASS_NAME);
- } else { // must be plain, ensured by TypeAttribute
- setClassname(PLAIN_FORMATTER_CLASS_NAME);
+ } else {
+ if ("failure".equals(type.getValue())) {
+ setClassname(FAILURE_RECORDER_CLASS_NAME);
+ } else { // must be plain, ensured by TypeAttribute
+ setClassname(PLAIN_FORMATTER_CLASS_NAME);
+ }
}
}
}
@@ -268,14 +278,14 @@ public class FormatterElement {
}
/**
- *
Enumerated attribute with the values "plain", "xml" and "brief". + *
Enumerated attribute with the values "plain", "xml", "brief" and "failure". * *
Use to enumerate options for type
attribute.
*/
public static class TypeAttribute extends EnumeratedAttribute {
/** {@inheritDoc}. */
public String[] getValues() {
- return new String[] {"plain", "xml", "brief"};
+ return new String[] {"plain", "xml", "brief", "failure"};
}
}
}
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
index e8c311679..bf12c5f94 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
@@ -163,7 +163,7 @@ public class JUnitTask extends Task {
private JUnitTaskMirror delegate;
/** A boolean on whether to get the forked path for ant classes */
- private boolean forkedPathChecked = false;
+ private boolean forkedPathChecked = false;
// Attributes for basetest
private boolean haltOnError = false;
diff --git a/src/tests/junit/org/apache/tools/ant/BuildFileTest.java b/src/tests/junit/org/apache/tools/ant/BuildFileTest.java
index 5a628f9b2..2273826fc 100644
--- a/src/tests/junit/org/apache/tools/ant/BuildFileTest.java
+++ b/src/tests/junit/org/apache/tools/ant/BuildFileTest.java
@@ -18,11 +18,11 @@
package org.apache.tools.ant;
-import junit.framework.TestCase;
import java.io.File;
import java.io.PrintStream;
import java.net.URL;
-import java.util.Hashtable;
+
+import junit.framework.TestCase;
/**
* A BuildFileTest is a TestCase which executes targets from an Ant buildfile
@@ -117,18 +117,35 @@ public abstract class BuildFileTest extends TestCase {
/**
* Assert that the given substring is in the output messages.
+ * @param message Print this message if the test fails. Defaults to
+ * a meaningful text if null is passed.
* @since Ant1.7
*/
- public void assertOutputContaining(String substring) {
+ public void assertOutputContaining(String message, String substring) {
String realOutput = getOutput();
- assertTrue("expecting output to contain \"" + substring
- + "\" output was \"" + realOutput + "\"",
- realOutput.indexOf(substring) >= 0);
+ String realMessage = (message != null)
+ ? message
+ : "expecting output to contain \"" + substring + "\" output was \"" + realOutput + "\"";
+ assertTrue(realMessage, realOutput.indexOf(substring) >= 0);
}
/**
- * Assert that the given message has been logged with a priority
- * <= INFO when running the given target.
+ * Assert that the given substring is not in the output messages.
+ * @param message Print this message if the test fails. Defaults to
+ * a meaningful text if null is passed.
+ * @since Ant1.7
+ */
+ public void assertOutputNotContaining(String message, String substring) {
+ String realOutput = getOutput();
+ String realMessage = (message != null)
+ ? message
+ : "expecting output to contain \"" + substring + "\" output was \"" + realOutput + "\"";
+ assertFalse(realMessage, realOutput.indexOf(substring) >= 0);
+ }
+
+ /**
+ * Assert that the given message has been logged with a priority <= INFO when running the
+ * given target.
*/
public void expectLogContaining(String target, String log) {
executeTarget(target);
diff --git a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskTest.java b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskTest.java
index bce4d3791..d57c6b72b 100644
--- a/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskTest.java
+++ b/src/tests/junit/org/apache/tools/ant/taskdefs/optional/junit/JUnitTaskTest.java
@@ -17,31 +17,31 @@
*/
package org.apache.tools.ant.taskdefs.optional.junit;
-import org.apache.tools.ant.BuildFileTest;
import java.io.BufferedReader;
+import java.io.File;
import java.io.FileReader;
import java.io.IOException;
+import org.apache.tools.ant.BuildFileTest;
+
public class JUnitTaskTest extends BuildFileTest {
/**
- * Constructor for the JUnitTaskTest object
+ * Constructor for the JUnitTaskTest object.
*/
public JUnitTaskTest(String name) {
super(name);
}
-
/**
- * The JUnit setup method
+ * The JUnit setup method.
*/
public void setUp() {
configureProject("src/etc/testcases/taskdefs/optional/junit.xml");
}
-
/**
- * The teardown method for JUnit
+ * The teardown method for JUnit.
*/
public void tearDown() {
executeTarget("cleanup");
@@ -86,7 +86,83 @@ public class JUnitTaskTest extends BuildFileTest {
public void testBatchTestForkOnceExtension() {
assertResultFilesExist("testBatchTestForkOnceExtension", ".foo");
}
-
+
+ /* Bugzilla Report 42984 */
+ //TODO This scenario works from command line, but not from JUnit ...
+ // See the _run.bat attachement of the bug.
+ public void _testFailureRecorder() {
+ File testDir = new File(getProjectDir(), "out");
+ File collectorFile = new File(getProjectDir(), "out/FailedTests.java");
+
+ // ensure that there is a clean test environment
+ assertFalse("Test directory must not exist before the test preparation.",
+ testDir.exists());
+ assertFalse("The collector file must not exist before the test preparation.",
+ collectorFile.exists());
+
+ // prepare the test environment
+ executeTarget("failureRecorder.prepare");
+ assertTrue("Test directory was not created.", testDir.exists());
+ assertTrue("There should be one class.", (new File(testDir, "A.class")).exists());
+ assertFalse("The collector file " + collectorFile.getAbsolutePath()
+ + " should not exist before the 1st run.", collectorFile.exists());
+
+ // 1st junit run: should do all tests - failing and not failing tests
+ executeTarget("failureRecorder.runtest");
+ assertTrue("The collector file " + collectorFile.getAbsolutePath()
+ + " should exist after the 1st run.", collectorFile.exists());
+ // the passing test cases
+ assertOutputContaining("1st run: should run A.test01", "A.test01");
+ assertOutputContaining("1st run: should run B.test05", "B.test05");
+ assertOutputContaining("1st run: should run B.test06", "B.test06");
+ assertOutputContaining("1st run: should run C.test07", "C.test07");
+ assertOutputContaining("1st run: should run C.test08", "C.test08");
+ assertOutputContaining("1st run: should run C.test09", "C.test09");
+ // the failing test cases
+ assertOutputContaining("1st run: should run A.test02", "A.test02");
+ assertOutputContaining("1st run: should run A.test03", "A.test03");
+ assertOutputContaining("1st run: should run B.test04", "B.test04");
+ assertOutputContaining("1st run: should run D.test10", "D.test10");
+
+ // 2nd junit run: should do only failing tests
+ executeTarget("failureRecorder.runtest");
+ assertTrue("The collector file " + collectorFile.getAbsolutePath()
+ + " should exist after the 2nd run.", collectorFile.exists());
+ // the passing test cases
+ assertOutputNotContaining("2nd run: should not run A.test01", "A.test01");
+ assertOutputNotContaining("2nd run: should not run A.test05", "B.test05");
+ assertOutputNotContaining("2nd run: should not run B.test06", "B.test06");
+ assertOutputNotContaining("2nd run: should not run C.test07", "C.test07");
+ assertOutputNotContaining("2nd run: should not run C.test08", "C.test08");
+ assertOutputNotContaining("2nd run: should not run C.test09", "C.test09");
+ // the failing test cases
+ assertOutputContaining("2nd run: should run A.test02", "A.test02");
+ assertOutputContaining("2nd run: should run A.test03", "A.test03");
+ assertOutputContaining("2nd run: should run B.test04", "B.test04");
+ assertOutputContaining("2nd run: should run D.test10", "D.test10");
+
+ // "fix" errors in class A
+ executeTarget("failureRecorder.fixing");
+
+ // 3rd run: four running tests with two errors
+ executeTarget("failureRecorder.runtest");
+ assertTrue("The collector file " + collectorFile.getAbsolutePath()
+ + " should exist after the 3rd run.", collectorFile.exists());
+ assertOutputContaining("3rd run: should run A.test02", "A.test02");
+ assertOutputContaining("3rd run: should run A.test03", "A.test03");
+ assertOutputContaining("3rd run: should run B.test04", "B.test04");
+ assertOutputContaining("3rd run: should run D.test10", "D.test10");
+
+ // 4rd run: two running tests with errors
+ executeTarget("failureRecorder.runtest");
+ assertTrue("The collector file " + collectorFile.getAbsolutePath()
+ + " should exist after the 4th run.", collectorFile.exists());
+ assertOutputNotContaining("4th run: should not run A.test02", "A.test02");
+ assertOutputNotContaining("4th run: should not run A.test03", "A.test03");
+ assertOutputContaining("4th run: should run B.test04", "B.test04");
+ assertOutputContaining("4th run: should run D.test10", "D.test10");
+ }
+
public void testBatchTestForkOnceCustomFormatter() {
assertResultFilesExist("testBatchTestForkOnceCustomFormatter", "foo");
}
@@ -155,5 +231,4 @@ public class JUnitTaskTest extends BuildFileTest {
assertEquals(search, line);
}
-}
-
+}
\ No newline at end of file