There is no automatic testcase for this, but if your run ant -f src/etc/testcases/taskdefs/optional/junit.xml -Dshowoutput=off ant -f src/etc/testcases/taskdefs/optional/junit.xml -Dshowoutput=on you'll see it in action. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272496 13f79535-47bb-0310-9956-ffa450edef68master
@@ -4,10 +4,6 @@ Changes from Ant 1.4.1 to current CVS version | |||
Changes that could break older environments: | |||
-------------------------------------------- | |||
* Shipped XML parser is now Xerces 2.0.1 along with the XML Parser APIs. | |||
XML Parser APIs is a separate jar that contains the necessary | |||
JAXP/DOM/SAX classes. | |||
* Important: Single $ signs are no longer silently stripped! | |||
Before you panic that we have broken all your build files, we have kept | |||
the old "$$" -> "$" behaviour. So only build files which accidentally had | |||
@@ -16,6 +12,10 @@ Changes that could break older environments: | |||
build file which works on ant versions 1.4.1 or earlier, stay with | |||
the double $$ sign rule. | |||
* Shipped XML parser is now Xerces 2.0.1 along with the XML Parser APIs. | |||
XML Parser APIs is a separate jar that contains the necessary | |||
JAXP/DOM/SAX classes. | |||
* <telnet> was fixed to expand properties inside nested <read> and | |||
<write> elements; before this only happened when you assigned the text | |||
to the string attribute. If you had $ signs in the string, they may | |||
@@ -321,6 +321,11 @@ Other changes: | |||
* org.apache.tools.ant.XmlLogger now is a BuildLogger, rather than just | |||
a BuildListener. It can operate in either mode successfully. | |||
* <junit> has a new attribute "showoutput". If set to true, output | |||
generated by tests will be sent to Ant's logging system as well as | |||
to the formatters (instead of sending it to the formatters | |||
exclusively). | |||
Changes from Ant 1.4 to Ant 1.4.1 | |||
=========================================== | |||
@@ -340,27 +340,6 @@ | |||
<font color="#000000" size="-1" face="arial,helvetica,sanserif"> | |||
Stefan, others welcome | |||
</font> | |||
</td> | |||
</tr> | |||
<tr> | |||
<td bgcolor="#a0ddf0" colspan="" rowspan="" | |||
valign="top" align="left"> | |||
<font color="#000000" size="-1" face="arial,helvetica,sanserif"> | |||
JUnit's System.err/.out handling | |||
</font> | |||
</td> | |||
<td bgcolor="#a0ddf0" colspan="" rowspan="" | |||
valign="top" align="left"> | |||
<font color="#000000" size="-1" face="arial,helvetica,sanserif"> | |||
Currently this is coupled to SummaryResultFormatter - | |||
no SummaryFormatter, no output. Want to decouple it. | |||
</font> | |||
</td> | |||
<td bgcolor="#a0ddf0" colspan="" rowspan="" | |||
valign="top" align="left"> | |||
<font color="#000000" size="-1" face="arial,helvetica,sanserif"> | |||
Stefan, others welcome | |||
</font> | |||
</td> | |||
</tr> | |||
<tr> | |||
@@ -494,7 +473,28 @@ | |||
<td bgcolor="#a0ddf0" colspan="" rowspan="" | |||
valign="top" align="left"> | |||
<font color="#000000" size="-1" face="arial,helvetica,sanserif"> | |||
Stefan, others welcome | |||
Stefan | |||
</font> | |||
</td> | |||
</tr> | |||
<tr> | |||
<td bgcolor="#a0ddf0" colspan="" rowspan="" | |||
valign="top" align="left"> | |||
<font color="#000000" size="-1" face="arial,helvetica,sanserif"> | |||
JUnit's System.err/.out handling | |||
</font> | |||
</td> | |||
<td bgcolor="#a0ddf0" colspan="" rowspan="" | |||
valign="top" align="left"> | |||
<font color="#000000" size="-1" face="arial,helvetica,sanserif"> | |||
showoutput attribute has been added - doesn't work in | |||
some cases yet (same reason as bug PR 7980) | |||
</font> | |||
</td> | |||
<td bgcolor="#a0ddf0" colspan="" rowspan="" | |||
valign="top" align="left"> | |||
<font color="#000000" size="-1" face="arial,helvetica,sanserif"> | |||
Stefan | |||
</font> | |||
</td> | |||
</tr> | |||
@@ -135,6 +135,13 @@ elements</a>).</p> | |||
the tests and JUnit to the classpath in forked mode.</td> | |||
<td align="center" valign="top">No; default is <code>true</code>.</td> | |||
</tr> | |||
<tr> | |||
<td valign="top">showoutput</td> | |||
<td valign="top">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.</td> | |||
<td align="center" valign="top">No</td> | |||
</tr> | |||
</table> | |||
<p>By using the <code>errorproperty</code> and <code>failureproperty</code> | |||
@@ -1,34 +1,39 @@ | |||
<?xml version="1.0"?> | |||
<project name="junit-test" basedir="." default="outputTests"> | |||
<property name="showoutput" value="false" /> | |||
<path id="test"> | |||
<pathelement path="${java.class.path}" /> | |||
<pathelement location="../../../../../build/testcases" /> | |||
</path> | |||
<target name="testForkedOutput"> | |||
<junit fork="yes" haltonerror="true" haltonfailure="true"> | |||
<junit fork="yes" haltonerror="true" haltonfailure="true" | |||
showoutput="${showoutput}"> | |||
<test name="org.example.junit.Output" /> | |||
<classpath refid="test" /> | |||
</junit> | |||
</target> | |||
<target name="testNonForkedOutput"> | |||
<junit fork="false" haltonerror="true" haltonfailure="true"> | |||
<junit fork="false" haltonerror="true" haltonfailure="true" | |||
showoutput="${showoutput}"> | |||
<test name="org.example.junit.Output" /> | |||
<classpath refid="test" /> | |||
</junit> | |||
</target> | |||
<target name="testForkedThreadedOutput"> | |||
<junit fork="yes" haltonerror="true" haltonfailure="true"> | |||
<junit fork="yes" haltonerror="true" haltonfailure="true" | |||
showoutput="${showoutput}"> | |||
<test name="org.example.junit.ThreadedOutput" /> | |||
<classpath refid="test" /> | |||
</junit> | |||
</target> | |||
<target name="testNonForkedThreadedOutput"> | |||
<junit fork="false" haltonerror="true" haltonfailure="true"> | |||
<junit fork="false" haltonerror="true" haltonfailure="true" | |||
showoutput="${showoutput}"> | |||
<test name="org.example.junit.ThreadedOutput" /> | |||
<classpath refid="test" /> | |||
</junit> | |||
@@ -172,6 +172,8 @@ public class JUnitTask extends Task { | |||
private boolean includeAntRuntime = true; | |||
private Path antRuntimeClasses = null; | |||
private boolean showOutput = false; | |||
/** | |||
* Tells this task whether to smartly filter the stack frames of | |||
* JUnit testcase errors and failures before reporting them. | |||
@@ -467,6 +469,20 @@ public class JUnitTask extends Task { | |||
includeAntRuntime = b; | |||
} | |||
/** | |||
* Whether to send output of the testcases to Ant's logging system or not. | |||
* | |||
* <p>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.</p> | |||
* | |||
* @since Ant 1.5 | |||
*/ | |||
public void setShowOutput(boolean showOutput) { | |||
this.showOutput = showOutput; | |||
} | |||
/** | |||
* Creates a new JUnitRunner and enables fork of a new Java VM. | |||
* | |||
@@ -590,6 +606,9 @@ public class JUnitTask extends Task { | |||
.setValue("formatter=org.apache.tools.ant.taskdefs.optional.junit.SummaryJUnitResultFormatter"); | |||
} | |||
cmd.createArgument().setValue("showoutput=" | |||
+ String.valueOf(showOutput)); | |||
StringBuffer formatterArg = new StringBuffer(128); | |||
final FormatterElement[] feArray = mergeFormatters(test); | |||
for (int i = 0; i < feArray.length; i++) { | |||
@@ -674,6 +693,9 @@ public class JUnitTask extends Task { | |||
protected void handleOutput(String line) { | |||
if (runner != null) { | |||
runner.handleOutput(line); | |||
if (showOutput) { | |||
super.handleOutput(line); | |||
} | |||
} else { | |||
super.handleOutput(line); | |||
} | |||
@@ -688,6 +710,9 @@ public class JUnitTask extends Task { | |||
protected void handleErrorOutput(String line) { | |||
if (runner != null) { | |||
runner.handleErrorOutput(line); | |||
if (showOutput) { | |||
super.handleErrorOutput(line); | |||
} | |||
} else { | |||
super.handleErrorOutput(line); | |||
} | |||
@@ -65,19 +65,20 @@ import junit.framework.Test; | |||
import junit.framework.TestSuite; | |||
import junit.framework.AssertionFailedError; | |||
import java.lang.reflect.Method; | |||
import java.io.BufferedReader; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.io.PrintStream; | |||
import java.io.PrintWriter; | |||
import java.io.StringReader; | |||
import java.io.StringWriter; | |||
import java.io.ByteArrayOutputStream; | |||
import java.io.IOException; | |||
import java.io.FileInputStream; | |||
import java.io.File; | |||
import java.util.Enumeration; | |||
import java.util.Hashtable; | |||
import java.util.Properties; | |||
import java.util.Vector; | |||
/** | |||
@@ -90,13 +91,15 @@ import java.util.Vector; | |||
* public static junit.framework.Test suite() | |||
* </code></pre> | |||
* | |||
* <p> If no such method exists, all public methods starting with "test" and taking no | |||
* argument will be run. | |||
* <p> If no such method exists, all public methods starting with | |||
* "test" and taking no argument will be run. | |||
* | |||
* <p> Summary output is generated at the end. | |||
* | |||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | |||
* @author <a href="mailto:ehatcher@apache.org">Erik Hatcher</a> | |||
* | |||
* @since Ant 1.2 | |||
*/ | |||
public class JUnitTestRunner implements TestListener { | |||
@@ -131,6 +134,11 @@ public class JUnitTestRunner implements TestListener { | |||
*/ | |||
private static boolean filtertrace = true; | |||
/** | |||
* Do we send output to System.out/.err in addition to the formatters? | |||
*/ | |||
private boolean showOutput = false; | |||
private static final String[] DEFAULT_TRACE_FILTERS = new String[] { | |||
"junit.framework.TestCase", | |||
"junit.framework.TestResult", | |||
@@ -187,20 +195,41 @@ public class JUnitTestRunner implements TestListener { | |||
* Constructor for fork=true or when the user hasn't specified a | |||
* classpath. | |||
*/ | |||
public JUnitTestRunner(JUnitTest test, boolean haltOnError, boolean filtertrace, | |||
boolean haltOnFailure) { | |||
this(test, haltOnError, filtertrace, haltOnFailure, null); | |||
public JUnitTestRunner(JUnitTest test, boolean haltOnError, | |||
boolean filtertrace, boolean haltOnFailure) { | |||
this(test, haltOnError, filtertrace, haltOnFailure, false); | |||
} | |||
/** | |||
* Constructor for fork=true or when the user hasn't specified a | |||
* classpath. | |||
*/ | |||
public JUnitTestRunner(JUnitTest test, boolean haltOnError, | |||
boolean filtertrace, boolean haltOnFailure, | |||
boolean showOutput) { | |||
this(test, haltOnError, filtertrace, haltOnFailure, showOutput, null); | |||
} | |||
/** | |||
* Constructor to use when the user has specified a classpath. | |||
*/ | |||
public JUnitTestRunner(JUnitTest test, boolean haltOnError, boolean filtertrace, | |||
boolean haltOnFailure, ClassLoader loader) { | |||
public JUnitTestRunner(JUnitTest test, boolean haltOnError, | |||
boolean filtertrace, boolean haltOnFailure, | |||
ClassLoader loader) { | |||
this(test, haltOnError, filtertrace, haltOnFailure, false, loader); | |||
} | |||
/** | |||
* Constructor to use when the user has specified a classpath. | |||
*/ | |||
public JUnitTestRunner(JUnitTest test, boolean haltOnError, | |||
boolean filtertrace, boolean haltOnFailure, | |||
boolean showOutput, ClassLoader loader) { | |||
this.filtertrace = filtertrace; | |||
this.junitTest = test; | |||
this.haltOnError = haltOnError; | |||
this.haltOnFailure = haltOnFailure; | |||
this.showOutput = showOutput; | |||
try { | |||
Class testClass = null; | |||
@@ -269,9 +298,26 @@ public class JUnitTestRunner implements TestListener { | |||
if (forked) { | |||
savedOut = System.out; | |||
System.setOut(systemOut); | |||
savedErr = System.err; | |||
System.setErr(systemError); | |||
if (!showOutput) { | |||
System.setOut(systemOut); | |||
System.setErr(systemError); | |||
} else { | |||
System.setOut(new PrintStream( | |||
new TeeOutputStream( | |||
new OutputStream[] {savedOut, | |||
systemOut} | |||
) | |||
) | |||
); | |||
System.setErr(new PrintStream( | |||
new TeeOutputStream( | |||
new OutputStream[] {savedErr, | |||
systemError} | |||
) | |||
) | |||
); | |||
} | |||
} | |||
@@ -384,13 +430,15 @@ public class JUnitTestRunner implements TestListener { | |||
private void fireStartTestSuite() { | |||
for (int i = 0; i < formatters.size(); i++) { | |||
((JUnitResultFormatter) formatters.elementAt(i)).startTestSuite(junitTest); | |||
((JUnitResultFormatter) formatters.elementAt(i)) | |||
.startTestSuite(junitTest); | |||
} | |||
} | |||
private void fireEndTestSuite() { | |||
for (int i = 0; i < formatters.size(); i++) { | |||
((JUnitResultFormatter) formatters.elementAt(i)).endTestSuite(junitTest); | |||
((JUnitResultFormatter) formatters.elementAt(i)) | |||
.endTestSuite(junitTest); | |||
} | |||
} | |||
@@ -417,6 +465,9 @@ public class JUnitTestRunner implements TestListener { | |||
* classname,filename. If filename is ommitted, System.out is | |||
* assumed.</td><td>none</td></tr> | |||
* | |||
* <tr><td>showoutput</td><td>send output to System.err/.out as | |||
* well as to the formatters?</td><td>false</td></tr> | |||
* | |||
* </table> | |||
*/ | |||
public static void main(String[] args) throws IOException { | |||
@@ -425,6 +476,7 @@ public class JUnitTestRunner implements TestListener { | |||
boolean haltFail = false; | |||
boolean stackfilter = true; | |||
Properties props = new Properties(); | |||
boolean showOut = false; | |||
if (args.length == 0) { | |||
System.err.println("required argument TestClassName missing"); | |||
@@ -446,9 +498,12 @@ public class JUnitTestRunner implements TestListener { | |||
System.exit(ERRORS); | |||
} | |||
} else if (args[i].startsWith("propsfile=")) { | |||
FileInputStream in = new FileInputStream(args[i].substring(10)); | |||
FileInputStream in = new FileInputStream(args[i] | |||
.substring(10)); | |||
props.load(in); | |||
in.close(); | |||
} else if (args[i].startsWith("showoutput=")) { | |||
showOut = Project.toBoolean(args[i].substring(11)); | |||
} | |||
} | |||
@@ -462,7 +517,8 @@ public class JUnitTestRunner implements TestListener { | |||
} | |||
t.setProperties(props); | |||
JUnitTestRunner runner = new JUnitTestRunner(t, haltError, stackfilter, haltFail); | |||
JUnitTestRunner runner = new JUnitTestRunner(t, haltError, stackfilter, | |||
haltFail, showOut); | |||
runner.forked = true; | |||
transferFormatters(runner); | |||
runner.run(); | |||
@@ -473,7 +529,8 @@ public class JUnitTestRunner implements TestListener { | |||
private static void transferFormatters(JUnitTestRunner runner) { | |||
for (int i = 0; i < fromCmdLine.size(); i++) { | |||
runner.addFormatter((JUnitResultFormatter) fromCmdLine.elementAt(i)); | |||
runner.addFormatter((JUnitResultFormatter) fromCmdLine | |||
.elementAt(i)); | |||
} | |||
} | |||
@@ -537,4 +594,25 @@ public class JUnitTestRunner implements TestListener { | |||
return false; | |||
} | |||
/** | |||
* Helper class that sends output sent to multiple streams. | |||
* | |||
* @since Ant 1.5 | |||
*/ | |||
private class TeeOutputStream extends OutputStream { | |||
private OutputStream[] outs; | |||
private TeeOutputStream(OutputStream[] outs) { | |||
this.outs = outs; | |||
} | |||
public void write(int b) throws IOException { | |||
for (int i = 0; i < outs.length; i++) { | |||
outs[i].write(b); | |||
} | |||
} | |||
} | |||
} // JUnitTestRunner |
@@ -89,13 +89,6 @@ | |||
<td>Stefan, others welcome</td> | |||
</tr> | |||
<tr> | |||
<td>JUnit's System.err/.out handling</td> | |||
<td>Currently this is coupled to SummaryResultFormatter - | |||
no SummaryFormatter, no output. Want to decouple it.</td> | |||
<td>Stefan, others welcome</td> | |||
</tr> | |||
<tr> | |||
<td>Make javadoc a real directory based task</td> | |||
<td></td> | |||
@@ -141,8 +134,15 @@ | |||
<td>PGP signing task if possible</td> | |||
<td>Not done, but deemed impossible - at least in the 1.5 | |||
time frame.</td> | |||
<td>Stefan, others welcome</td> | |||
<td>Stefan</td> | |||
</tr> | |||
<tr> | |||
<td>JUnit's System.err/.out handling</td> | |||
<td>showoutput attribute has been added - doesn't work in | |||
some cases yet (same reason as bug PR 7980)</td> | |||
<td>Stefan</td> | |||
</tr> | |||
</table> | |||
</subsection> | |||