diff --git a/WHATSNEW b/WHATSNEW index 4a4fa6957..75d8442a5 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -15,6 +15,9 @@ Changes that could break older environments: * The task has been move to a package of its own. +* JUnitResultFormater has two additional methods that must be + implemented by custom formatters. + Other changes: -------------- @@ -50,6 +53,8 @@ Other changes: with the "file" attribute to specify whether the "file" you're looking for is a file or a directory. +* New formatter named "brief" + Fixed bugs: ----------- @@ -80,6 +85,9 @@ Fixed bugs: * If the quiet attribute has been set, will handle s with non-existing directories gracefully. +* Output written by testcases will now be captured by the task + and passed to the formatters. + Changes from Ant 1.2 to Ant 1.3 =========================================== diff --git a/build.xml b/build.xml index 65e71dd4b..425df378d 100644 --- a/build.xml +++ b/build.xml @@ -615,7 +615,7 @@ - + diff --git a/docs/manual/OptionalTasks/junit.html b/docs/manual/OptionalTasks/junit.html index f79e0929d..4c4d43c42 100644 --- a/docs/manual/OptionalTasks/junit.html +++ b/docs/manual/OptionalTasks/junit.html @@ -25,7 +25,11 @@ elements.

printsummary - Print one line statistics for each testcase. + Print one line statistics for each testcase. Can + take the values "on", "off" and + "withOutAndErr" - "withOutAndErr" is the same + as "on" but also includes the test's output + (written to System.out and System.err). No, default is "off" @@ -122,9 +126,11 @@ usefile attribute to false, the name of the file is determined by the name of the test and can be set by the outfile attribute of <test>. -

There are two predefined formatters, one prints the test results in -XML format, the other emits plain text. Custom formatters that need to -implement +

There are three predefined formatters, one prints the test results +in XML format, the other emit plain text. The formatter named +"brief" will only print detailed information for testcases +that failed, while "plain" gives a little statistics line +for all test cases. Custom formatters that need to implement org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter can be specified.

@@ -136,7 +142,8 @@ can be specified.

type - Use a predefined formatter (either "xml" or "plain"). + Use a predefined formatter (either + "xml", "plain" or "brief"). Exactly one of these. diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/BriefJUnitResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/BriefJUnitResultFormatter.java new file mode 100644 index 000000000..6065f7bca --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/BriefJUnitResultFormatter.java @@ -0,0 +1,239 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Ant", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.apache.tools.ant.taskdefs.optional.junit; + +import org.apache.tools.ant.BuildException; + +import junit.framework.*; + +/** + * Prints plain text output of the test to a specified Writer. + * Inspired by the PlainJUnitResultFormatter. + * @author Robert Watkins + */ +public class BriefJUnitResultFormatter implements JUnitResultFormatter { + + /** + * Where to write the log to. + */ + private java.io.OutputStream m_out; + + /** + * Used for writing the results. + */ + private java.io.PrintWriter m_output; + + /** + * Used as part of formatting the results. + */ + private java.io.StringWriter m_results; + + /** + * Used for writing formatted results to. + */ + private java.io.PrintWriter m_resultWriter; + + /** + * Formatter for timings. + */ + private java.text.NumberFormat m_numberFormat = java.text.NumberFormat.getInstance(); + + /** + * Output suite has written to System.out + */ + private String systemOutput = null; + + /** + * Output suite has written to System.err + */ + private String systemError = null; + + public BriefJUnitResultFormatter() { + m_results = new java.io.StringWriter(); + m_resultWriter = new java.io.PrintWriter(m_results); + } + + /** + * Sets the stream the formatter is supposed to write its results to. + */ + public void setOutput(java.io.OutputStream out) { + m_out = out; + m_output = new java.io.PrintWriter(out); + } + + public void setSystemOutput(String out) { + systemOutput = out; + } + + public void setSystemError(String err) { + systemError = err; + } + + protected java.io.PrintWriter output() { return m_output; } + + protected java.io.PrintWriter resultWriter() { return m_resultWriter; } + + /** + * The whole testsuite started. + */ + public void startTestSuite(JUnitTest suite) throws BuildException { + } + + /** + * The whole testsuite ended. + */ + public void endTestSuite(JUnitTest suite) throws BuildException { + String newLine = System.getProperty("line.separator"); + StringBuffer sb = new StringBuffer("Testsuite: "); + sb.append(suite.getName()); + sb.append(newLine); + sb.append("Tests run: "); + sb.append(suite.runCount()); + sb.append(", Failures: "); + sb.append(suite.failureCount()); + sb.append(", Errors: "); + sb.append(suite.errorCount()); + sb.append(", Time elapsed: "); + sb.append(m_numberFormat.format(suite.getRunTime()/1000.0)); + sb.append(" sec"); + sb.append(newLine); + sb.append(newLine); + + // append the err and output streams to the log + if (systemOutput != null && systemOutput.length() > 0) { + sb.append("------------- Standard Output ---------------" ) + .append(newLine) + .append(systemOutput) + .append("------------- ---------------- ---------------" ) + .append(newLine); + } + + if (systemError != null && systemError.length() > 0) { + sb.append("------------- Standard Error -----------------" ) + .append(newLine) + .append(systemError) + .append("------------- ---------------- ---------------" ) + .append(newLine); + } + + if ( output() != null) { + try { + output().write(sb.toString()); + resultWriter().close(); + output().write(m_results.toString()); + output().flush(); + } finally { + if (m_out != (Object)System.out && + m_out != (Object)System.err) { + try { + m_out.close(); + } catch (java.io.IOException e) {} + } + } + } + } + + /** + * A test started. + */ + public void startTest(Test test) { + } + + /** + * A test ended. + */ + public void endTest(Test test) { + } + + /** + * A test failed. + */ + public void addFailure(Test test, AssertionFailedError failure) { + formatError("\tFAILED", test, failure); + } + + /** + * A test caused an error. + */ + public void addError(Test test, Throwable error) { + formatError("\tCaused an ERROR", test, error); + } + + /** + * Format the test for printing.. + */ + protected String formatTest(Test test) { + if (test == null) { + return "Null Test: "; + } + else { + return "Testcase: " + test.toString() + ":"; + } + } + + /** + * Format an error and print it. + */ + protected void formatError(String type, Test test, Throwable error) { + if (test != null) { + endTest(test); + } + + resultWriter().println(formatTest(test) + ":" + type); + resultWriter().println(error.getMessage()); + error.printStackTrace(resultWriter()); + resultWriter().println(""); + } +} diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java index 0120bf950..7fdb3dcba 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/FormatterElement.java @@ -79,8 +79,12 @@ public class FormatterElement { if ("xml".equals(type.getValue())) { setClassname("org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter"); setExtension(".xml"); - } else { // must be plain, ensured by TypeAttribute - setClassname("org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter"); + } else { + if ("brief".equals(type.getValue())) { + setClassname("org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"); + } else { // must be plain, ensured by TypeAttribute + setClassname("org.apache.tools.ant.taskdefs.optional.junit.PlainJUnitResultFormatter"); + } setExtension(".txt"); } } @@ -160,7 +164,7 @@ public class FormatterElement { */ public static class TypeAttribute extends EnumeratedAttribute { public String[] getValues() { - return new String[] {"plain", "xml"}; + return new String[] {"plain", "xml", "brief"}; } } }