Browse Source

Add new showoutput attribute to <junit>.

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-ffa450edef68
master
Stefan Bodewig 23 years ago
parent
commit
e7de779f7c
7 changed files with 177 additions and 57 deletions
  1. +9
    -4
      WHATSNEW
  2. +22
    -22
      docs/ant15_todo.html
  3. +7
    -0
      docs/manual/OptionalTasks/junit.html
  4. +9
    -4
      src/etc/testcases/taskdefs/optional/junit.xml
  5. +25
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
  6. +97
    -19
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
  7. +8
    -8
      xdocs/ant15_todo.xml

+ 9
- 4
WHATSNEW View File

@@ -4,10 +4,6 @@ Changes from Ant 1.4.1 to current CVS version
Changes that could break older environments: 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! * Important: Single $ signs are no longer silently stripped!
Before you panic that we have broken all your build files, we have kept Before you panic that we have broken all your build files, we have kept
the old "$$" -> "$" behaviour. So only build files which accidentally had 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 build file which works on ant versions 1.4.1 or earlier, stay with
the double $$ sign rule. 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 * <telnet> was fixed to expand properties inside nested <read> and
<write> elements; before this only happened when you assigned the text <write> elements; before this only happened when you assigned the text
to the string attribute. If you had $ signs in the string, they may 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 * org.apache.tools.ant.XmlLogger now is a BuildLogger, rather than just
a BuildListener. It can operate in either mode successfully. 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 Changes from Ant 1.4 to Ant 1.4.1
=========================================== ===========================================




+ 22
- 22
docs/ant15_todo.html View File

@@ -340,27 +340,6 @@
<font color="#000000" size="-1" face="arial,helvetica,sanserif"> <font color="#000000" size="-1" face="arial,helvetica,sanserif">
Stefan, others welcome Stefan, others welcome
</font> </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> </td>
</tr> </tr>
<tr> <tr>
@@ -494,7 +473,28 @@
<td bgcolor="#a0ddf0" colspan="" rowspan="" <td bgcolor="#a0ddf0" colspan="" rowspan=""
valign="top" align="left"> valign="top" align="left">
<font color="#000000" size="-1" face="arial,helvetica,sanserif"> <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> </font>
</td> </td>
</tr> </tr>


+ 7
- 0
docs/manual/OptionalTasks/junit.html View File

@@ -135,6 +135,13 @@ elements</a>).</p>
the tests and JUnit to the classpath in forked mode.</td> the tests and JUnit to the classpath in forked mode.</td>
<td align="center" valign="top">No; default is <code>true</code>.</td> <td align="center" valign="top">No; default is <code>true</code>.</td>
</tr> </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> </table>


<p>By using the <code>errorproperty</code> and <code>failureproperty</code> <p>By using the <code>errorproperty</code> and <code>failureproperty</code>


+ 9
- 4
src/etc/testcases/taskdefs/optional/junit.xml View File

@@ -1,34 +1,39 @@
<?xml version="1.0"?> <?xml version="1.0"?>


<project name="junit-test" basedir="." default="outputTests"> <project name="junit-test" basedir="." default="outputTests">
<property name="showoutput" value="false" />
<path id="test"> <path id="test">
<pathelement path="${java.class.path}" /> <pathelement path="${java.class.path}" />
<pathelement location="../../../../../build/testcases" /> <pathelement location="../../../../../build/testcases" />
</path> </path>


<target name="testForkedOutput"> <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" /> <test name="org.example.junit.Output" />
<classpath refid="test" /> <classpath refid="test" />
</junit> </junit>
</target> </target>


<target name="testNonForkedOutput"> <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" /> <test name="org.example.junit.Output" />
<classpath refid="test" /> <classpath refid="test" />
</junit> </junit>
</target> </target>


<target name="testForkedThreadedOutput"> <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" /> <test name="org.example.junit.ThreadedOutput" />
<classpath refid="test" /> <classpath refid="test" />
</junit> </junit>
</target> </target>


<target name="testNonForkedThreadedOutput"> <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" /> <test name="org.example.junit.ThreadedOutput" />
<classpath refid="test" /> <classpath refid="test" />
</junit> </junit>


+ 25
- 0
src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java View File

@@ -172,6 +172,8 @@ public class JUnitTask extends Task {
private boolean includeAntRuntime = true; private boolean includeAntRuntime = true;
private Path antRuntimeClasses = null; private Path antRuntimeClasses = null;


private boolean showOutput = false;

/** /**
* Tells this task whether to smartly filter the stack frames of * Tells this task whether to smartly filter the stack frames of
* JUnit testcase errors and failures before reporting them. * JUnit testcase errors and failures before reporting them.
@@ -467,6 +469,20 @@ public class JUnitTask extends Task {
includeAntRuntime = b; 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. * 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"); .setValue("formatter=org.apache.tools.ant.taskdefs.optional.junit.SummaryJUnitResultFormatter");
} }


cmd.createArgument().setValue("showoutput="
+ String.valueOf(showOutput));

StringBuffer formatterArg = new StringBuffer(128); StringBuffer formatterArg = new StringBuffer(128);
final FormatterElement[] feArray = mergeFormatters(test); final FormatterElement[] feArray = mergeFormatters(test);
for (int i = 0; i < feArray.length; i++) { for (int i = 0; i < feArray.length; i++) {
@@ -674,6 +693,9 @@ public class JUnitTask extends Task {
protected void handleOutput(String line) { protected void handleOutput(String line) {
if (runner != null) { if (runner != null) {
runner.handleOutput(line); runner.handleOutput(line);
if (showOutput) {
super.handleOutput(line);
}
} else { } else {
super.handleOutput(line); super.handleOutput(line);
} }
@@ -688,6 +710,9 @@ public class JUnitTask extends Task {
protected void handleErrorOutput(String line) { protected void handleErrorOutput(String line) {
if (runner != null) { if (runner != null) {
runner.handleErrorOutput(line); runner.handleErrorOutput(line);
if (showOutput) {
super.handleErrorOutput(line);
}
} else { } else {
super.handleErrorOutput(line); super.handleErrorOutput(line);
} }


+ 97
- 19
src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java View File

@@ -65,19 +65,20 @@ import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
import junit.framework.AssertionFailedError; import junit.framework.AssertionFailedError;
import java.lang.reflect.Method; import java.lang.reflect.Method;

import java.io.BufferedReader; 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.PrintStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringReader; import java.io.StringReader;
import java.io.StringWriter; 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.Enumeration;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Properties; import java.util.Properties;

import java.util.Vector; import java.util.Vector;


/** /**
@@ -90,13 +91,15 @@ import java.util.Vector;
* public static junit.framework.Test suite() * public static junit.framework.Test suite()
* </code></pre> * </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. * <p> Summary output is generated at the end.
* *
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
* @author <a href="mailto:ehatcher@apache.org">Erik Hatcher</a> * @author <a href="mailto:ehatcher@apache.org">Erik Hatcher</a>
*
* @since Ant 1.2
*/ */


public class JUnitTestRunner implements TestListener { public class JUnitTestRunner implements TestListener {
@@ -131,6 +134,11 @@ public class JUnitTestRunner implements TestListener {
*/ */
private static boolean filtertrace = true; 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[] { private static final String[] DEFAULT_TRACE_FILTERS = new String[] {
"junit.framework.TestCase", "junit.framework.TestCase",
"junit.framework.TestResult", "junit.framework.TestResult",
@@ -187,20 +195,41 @@ public class JUnitTestRunner implements TestListener {
* Constructor for fork=true or when the user hasn't specified a * Constructor for fork=true or when the user hasn't specified a
* classpath. * 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. * 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.filtertrace = filtertrace;
this.junitTest = test; this.junitTest = test;
this.haltOnError = haltOnError; this.haltOnError = haltOnError;
this.haltOnFailure = haltOnFailure; this.haltOnFailure = haltOnFailure;
this.showOutput = showOutput;


try { try {
Class testClass = null; Class testClass = null;
@@ -269,9 +298,26 @@ public class JUnitTestRunner implements TestListener {


if (forked) { if (forked) {
savedOut = System.out; savedOut = System.out;
System.setOut(systemOut);
savedErr = System.err; 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() { private void fireStartTestSuite() {
for (int i = 0; i < formatters.size(); i++) { for (int i = 0; i < formatters.size(); i++) {
((JUnitResultFormatter) formatters.elementAt(i)).startTestSuite(junitTest);
((JUnitResultFormatter) formatters.elementAt(i))
.startTestSuite(junitTest);
} }
} }


private void fireEndTestSuite() { private void fireEndTestSuite() {
for (int i = 0; i < formatters.size(); i++) { 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 * classname,filename. If filename is ommitted, System.out is
* assumed.</td><td>none</td></tr> * 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> * </table>
*/ */
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
@@ -425,6 +476,7 @@ public class JUnitTestRunner implements TestListener {
boolean haltFail = false; boolean haltFail = false;
boolean stackfilter = true; boolean stackfilter = true;
Properties props = new Properties(); Properties props = new Properties();
boolean showOut = false;


if (args.length == 0) { if (args.length == 0) {
System.err.println("required argument TestClassName missing"); System.err.println("required argument TestClassName missing");
@@ -446,9 +498,12 @@ public class JUnitTestRunner implements TestListener {
System.exit(ERRORS); System.exit(ERRORS);
} }
} else if (args[i].startsWith("propsfile=")) { } 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); props.load(in);
in.close(); 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); t.setProperties(props);


JUnitTestRunner runner = new JUnitTestRunner(t, haltError, stackfilter, haltFail);
JUnitTestRunner runner = new JUnitTestRunner(t, haltError, stackfilter,
haltFail, showOut);
runner.forked = true; runner.forked = true;
transferFormatters(runner); transferFormatters(runner);
runner.run(); runner.run();
@@ -473,7 +529,8 @@ public class JUnitTestRunner implements TestListener {


private static void transferFormatters(JUnitTestRunner runner) { private static void transferFormatters(JUnitTestRunner runner) {
for (int i = 0; i < fromCmdLine.size(); i++) { 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; 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 } // JUnitTestRunner

+ 8
- 8
xdocs/ant15_todo.xml View File

@@ -89,13 +89,6 @@
<td>Stefan, others welcome</td> <td>Stefan, others welcome</td>
</tr> </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> <tr>
<td>Make javadoc a real directory based task</td> <td>Make javadoc a real directory based task</td>
<td></td> <td></td>
@@ -141,8 +134,15 @@
<td>PGP signing task if possible</td> <td>PGP signing task if possible</td>
<td>Not done, but deemed impossible - at least in the 1.5 <td>Not done, but deemed impossible - at least in the 1.5
time frame.</td> 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> </tr>

</table> </table>
</subsection> </subsection>




Loading…
Cancel
Save