From b10787b4a784b55c1ac7c9bbfdef79a8ea5bc54f Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Thu, 20 Jul 2000 10:02:05 +0000 Subject: [PATCH] Optional JUnit task. Submitted by: Thomas Haas git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@267806 13f79535-47bb-0310-9956-ffa450edef68 --- build.xml | 17 + .../tools/ant/taskdefs/defaults.properties | 1 + .../optional/junit/JUnitResultFormatter.java | 75 ++++ .../taskdefs/optional/junit/JUnitTask.java | 292 ++++++++++++++++ .../taskdefs/optional/junit/JUnitTest.java | 202 +++++++++++ .../optional/junit/JUnitTestRunner.java | 325 ++++++++++++++++++ .../junit/SummaryJUnitResultFormatter.java | 128 +++++++ .../junit/XMLJUnitResultFormatter.java | 235 +++++++++++++ 8 files changed, 1275 insertions(+) create mode 100644 src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitResultFormatter.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java create mode 100644 src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java diff --git a/build.xml b/build.xml index fe91e91b5..7a0c4a996 100644 --- a/build.xml +++ b/build.xml @@ -80,6 +80,7 @@ + @@ -266,6 +267,22 @@ + + . + */ + +package org.apache.tools.ant.taskdefs.optional.junit; + +import junit.framework.TestListener; + +/** + * This Interface describes classes that format the results of a JUnit + * testrun. + * + * @author Stefan Bodewig + */ +public interface JUnitResultFormatter extends TestListener { + /** + * The whole testsuite started. + */ + public void startTestSuite(JUnitTest suite); + + /** + * The whole testsuite ended. + */ + public void endTestSuite(JUnitTest suite); +} 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 new file mode 100644 index 000000000..0605d9742 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java @@ -0,0 +1,292 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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", "Tomcat", 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 org.apache.tools.ant.Path; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.*; +import org.apache.tools.ant.types.Commandline; +import org.apache.tools.ant.types.CommandlineJava; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import java.util.Enumeration; +import java.util.Vector; + +/** + * Ant task to run JUnit tests. + * + *

JUnit is a framework to create unit test. It has been initially + * created by Erich Gamma and Kent Beck. JUnit can be found at http://www.xprogramming.com/software.htm. + * + *

This ant task runs a single TestCase. By default it spans a new + * Java VM to prevent interferences between different testcases, + * unless fork has been disabled. + * + * @author Thomas Haas + */ +public class JUnitTask extends Task { + + // private final static int HALT_NOT = 1; + // private final static int HALT_IMMEDIATELY = 2; + // private final static int HALT_AT_END = 3; + + private CommandlineJava commandline = new CommandlineJava(); + private Vector tests = new Vector(); + + private JUnitTest defaults = new JUnitTest(); + private boolean defaultOutfile = true; + private Integer timeout = null; + + // private int haltOnError = HALT_AT_END; + // private int haltOnFailure = HALT_AT_END; + + /** + * Set the path to junit classes. + * @param junit path to junit classes. + */ + public void setJunit(String junit) { + commandline.createClasspath().createPathElement().setLocation(junit); + } + + public void setDefaulthaltonerror(boolean value) { + defaults.setHaltonerror(value); + } + + public void setDefaulthaltonfailure(boolean value) { + defaults.setHaltonfailure(value); + } + + public void setDefaultprintsummary(boolean value) { + defaults.setPrintsummary(value); + } + + public void setDefaultprintxml(boolean value) { + defaults.setPrintxml(value); + } + + public void setDefaultOutFile(boolean value) { + defaultOutfile = value; + } + + public void setTimeout(Integer value) { + timeout = value; + } + + public void setFork(boolean value) { + defaults.setFork(value); + } + + public void setJvm(String value) { + defaults.setName(value); + commandline.setVm(value); + } + + public void setJvmargs(String value) { + commandline.createVmArgument().setLine(value); + } + + + /** + * Set the classpath to be used by the testcase. + * @param classpath the classpath used to run the testcase. + */ + /*public void setClasspath(String classpath) { + this.classpath = classpath; + }*/ + + + public Path createClasspath() { + return commandline.createClasspath(); + } + + public JUnitTest createTest() { + final JUnitTest result; + result = new JUnitTest( + defaults.getFork(), + defaults.getHaltonerror(), + defaults.getHaltonfailure(), + defaults.getPrintsummary(), + defaults.getPrintxml(), + null, null); + + tests.addElement(result); + return result; + } + + + /** + * Creates a new JUnitRunner and enables fork of a new Java VM. + */ + public JUnitTask() throws Exception { + commandline.setClassname("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner"); + } + + /** + * Runs the testcase. + */ + public void execute() throws BuildException { + boolean errorOccurred = false; + boolean failureOccurred = false; + + final String oldclasspath = System.getProperty("java.class.path"); + + commandline.createClasspath().createPathElement().setPath(oldclasspath); + /* + * This doesn't work on JDK 1.1, should use a Classloader of our own + * anyway --SB + * + * System.setProperty("java.class.path", commandline.createClasspath().toString()); + */ + + Enumeration list = tests.elements(); + while (list.hasMoreElements()) { + final JUnitTest test = (JUnitTest)list.nextElement(); + + final String filename = "TEST-" + test.getName() + ".xml"; +// removed --SB +// if (new File(filename).exists()) { +// project.log("Skipping " + test.getName()); +// continue; +// } + project.log("Running " + test.getName()); + + if (defaultOutfile && (test.getOutfile() == null || + test.getOutfile().length() == 0)) { + +// removed --SB +// test.setOutfile("RUNNING-" + filename); + test.setOutfile(filename); + } + + int exitValue = 2; + + if (test.getFork()) { + try { + // Create a watchdog based on the timeout attribute + final Execute execute = new Execute(new PumpStreamHandler(), createWatchdog()); + final Commandline cmdl = new Commandline(); + cmdl.addLine(commandline.getCommandline()); + cmdl.addLine(test.getCommandline()); + execute.setCommandline(cmdl.getCommandline()); + log("Execute JUnit: " + cmdl, Project.MSG_VERBOSE); + exitValue = execute.execute(); + } + catch (IOException e) { + throw new BuildException("Process fork failed.", e, + location); + } + } else { + final Object[] arg = { test }; + final Class[] argType = { arg[0].getClass() }; + try { + final Class target = Class.forName("org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner"); + final Method main = target.getMethod("runTest", argType); + project.log("Load JUnit: " + test, Project.MSG_VERBOSE); + exitValue = ((Integer)main.invoke(null, arg)).intValue(); + } catch (InvocationTargetException e) { + Throwable t = e.getTargetException(); + String msg = "Running test failed: " + t.getMessage(); + throw new BuildException(msg, t, location); + } catch (Exception e) { + String msg = "Running test failed: " + e.getMessage(); + throw new BuildException(msg, e, location); + } + } + + boolean errorOccurredHere = exitValue == 2; + boolean failureOccurredHere = exitValue == 1; +// removed --SB +// if (exitValue != 0) { +// rename("RUNNING-" + filename, "ERROR-" + filename); +// } else { +// rename("RUNNING-" + filename, filename); +// } + // later distinguish HALT_AT_END case + if (errorOccurredHere && test.getHaltonerror() + || failureOccurredHere && test.getHaltonfailure()) { + throw new BuildException("JUNIT FAILED", location); + } else if (errorOccurredHere || failureOccurredHere) { + log("JUNIT FAILED", Project.MSG_ERR); + } + + // Update overall test status + errorOccurred = errorOccurred || errorOccurredHere ; + failureOccurred = failureOccurred || failureOccurredHere ; + } + + // later add HALT_AT_END option + // Then test errorOccurred and failureOccurred here. + } + + protected ExecuteWatchdog createWatchdog() throws BuildException { + if (timeout == null) return null; + return new ExecuteWatchdog(timeout.intValue()); + } + + private void rename(String source, String destination) throws BuildException { + final File src = new File(source); + final File dest = new File(destination); + + if (dest.exists()) dest.delete(); + src.renameTo(dest); + } +} diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java new file mode 100644 index 000000000..6ed484af4 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java @@ -0,0 +1,202 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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", "Tomcat", 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.Project; +import org.apache.tools.ant.types.Commandline; + +/** + * + * @author Thomas Haas + */ +public class JUnitTest { + private boolean systemExit = false; + private boolean haltOnError = false; + private boolean haltOnFail = false; + private boolean printSummary = true; + private boolean printXml = true; + private String name = null; + private String outfile = null; + private boolean fork = false; + + private long runs, failures, errors; + private long runTime; + + public JUnitTest() { + } + + public JUnitTest(boolean fork, boolean haltOnError, boolean haltOnFail, + boolean printSummary, boolean printXml, String name, + String outfile) { + this.fork = fork; + this.haltOnError = haltOnError; + this.haltOnFail = haltOnFail; + this.printSummary = printSummary; + this.printXml = printXml; + this.name = name; + this.outfile = outfile; + } + + public void setFork(boolean value) { + fork = value; + } + + public boolean getFork() { + return fork; + } + + public void setHaltonerror(boolean value) { + haltOnError = value; + } + + public void setHaltonfailure(boolean value) { + haltOnFail = value; + } + + public void setPrintsummary(boolean value) { + printSummary = value; + } + + public void setPrintxml(boolean value) { + printXml = value; + } + + public void setName(String value) { + name = value; + } + + public void setOutfile(String value) { + outfile = value; + } + + + public boolean getHaltonerror() { + return haltOnError; + } + + public boolean getHaltonfailure() { + return haltOnFail; + } + + public boolean getPrintsummary() { + return printSummary; + } + + public boolean getPrintxml() { + return printXml; + } + + public String getName() { + return name; + } + + public String getOutfile() { + return outfile; + } + + public void setCommandline(String [] args) { + for (int i=0; i. + */ + +package org.apache.tools.ant.taskdefs.optional.junit; + +import org.apache.tools.ant.Project; + +import junit.framework.*; +import java.lang.reflect.*; +import java.io.*; +import java.util.Vector; + +/** + * Simple Testrunner for JUnit that runs all tests of a testsuite. + * + *

This TestRunner expects a name of a TestCase class as its + * argument. If this class provides a static suite() method it will be + * called and the resulting Test will be run. + * + *

Otherwise all public methods starting with "test" and taking no + * argument will be run. + * + *

Summary output is generated at the end. + * + * @author Stefan Bodewig + */ + +public class JUnitTestRunner implements TestListener { + + /** + * Holds the registered formatters. + */ + private Vector formatters = new Vector(); + + /** + * Collects TestResults. + */ + private TestResult res; + + /** + * Flag for endTest. + */ + private boolean failed = true; + + /** + * The test I'm going to run. + */ + private JUnitTest junitTest; + + /** + * The corresponding testsuite. + */ + private Test suite = null; + + /** + * Returncode + */ + private int retCode = 0; + + public JUnitTestRunner(JUnitTest test) { + junitTest = test; + try { + if (junitTest.getPrintxml()) { + if (test.getOutfile() != null + && test.getOutfile().length() > 0) { + + addFormatter(new XMLJUnitResultFormatter( + new PrintWriter( + new FileWriter(test.getOutfile(), false) + ) + ) + ); + } else { + addFormatter(new XMLJUnitResultFormatter( + new PrintWriter( + new OutputStreamWriter(System.out), true) + ) + ); + } + } + + if (junitTest.getPrintsummary()) { + addFormatter(new SummaryJUnitResultFormatter()); + } + + Class testClass = Class.forName(junitTest.getName()); + + try { + Method suiteMethod= testClass.getMethod("suite", new Class[0]); + suite = (Test)suiteMethod.invoke(null, new Class[0]); + } catch(NoSuchMethodException e) { + } catch(InvocationTargetException e) { + } catch(IllegalAccessException e) { + } + + if (suite == null) { + // try to extract a test suite automatically + // this will generate warnings if the class is no suitable Test + suite= new TestSuite(testClass); + } + + res = new TestResult(); + res.addListener(this); + for (int i=0; i < formatters.size(); i++) { + res.addListener((TestListener)formatters.elementAt(i)); + } + + } catch(Exception e) { + retCode = 2; + + fireStartTestSuite(); + for (int i=0; i < formatters.size(); i++) { + ((TestListener)formatters.elementAt(i)).addError(null, e); + } + junitTest.setCounts(1, 0, 1); + junitTest.setRunTime(0); + fireEndTestSuite(); + } + } + + public void run() { + long start = System.currentTimeMillis(); + + if (retCode != 0) { // had an exception in the constructor + return; + } + + fireStartTestSuite(); + suite.run(res); + junitTest.setRunTime(System.currentTimeMillis()-start); + junitTest.setCounts(res.runCount(), res.failureCount(), + res.errorCount()); + fireEndTestSuite(); + + if (res.errorCount() != 0) { + retCode = 2; + } else if (res.failureCount() != 0) { + retCode = 1; + } + } + + /** + * Returns what System.exit() would return in the standalone version. + * + * @return 2 if errors occurred, 1 if tests failed else 0. + */ + public int getRetCode() { + return retCode; + } + + /** + * Interface TestListener. + * + *

A new Test is started. + */ + public void startTest(Test t) { + failed = false; + } + + /** + * Interface TestListener. + * + *

A Test is finished. + */ + public void endTest(Test test) { + } + + /** + * Interface TestListener. + * + *

A Test failed. + */ + public void addFailure(Test test, Throwable t) { + failed = true; + + if (junitTest.getHaltonfailure()) { + res.stop(); + } + } + + /** + * Interface TestListener. + * + *

An error occured while running the test. + */ + public void addError(Test test, Throwable t) { + failed = true; + + if (junitTest.getHaltonerror()) { + res.stop(); + } + } + + private void fireStartTestSuite() { + for (int i=0; i + * keydescriptiondefault value + * + * exitexit with System.exit after testcase is + * complete?true + * + * haltOnErrorhalt test on + * errors?false + * + * haltOnFailurehalt test on + * failures?false + * + * printSummaryprint summary to System.out? + * true + * + * printXMLgenerate XML report? + * false + * + * outfilewhere to print the XML report - a + * filename System.out + * + * + */ + public static void main(String[] args) throws IOException { + boolean exitAtEnd = true; + boolean haltError = false; + boolean haltFail = false; + boolean printSummary = true; + boolean printXml = false; + PrintWriter out = null; + + if (args.length == 0) { + System.err.println("required argument TestClassName missing"); + if (exitAtEnd) { + System.exit(2); + } + } else { + + JUnitTest test = new JUnitTest(); + test.setName(args[0]); + args[0] = null; + test.setCommandline(args); + JUnitTestRunner runner = new JUnitTestRunner(test); + runner.run(); + + if (exitAtEnd) { + System.exit(runner.getRetCode()); + } + } + } + + + public static int runTest(JUnitTest test) { + final JUnitTestRunner runner = new JUnitTestRunner(test); + runner.run(); + return runner.getRetCode(); + } + +} // JUnitTestRunner diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java new file mode 100644 index 000000000..4580b4db0 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java @@ -0,0 +1,128 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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", "Tomcat", 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 java.text.NumberFormat; +import junit.framework.Test; + +/** + * Prints short summary output of the test to System.out + * + * @author Stefan Bodewig + */ + +public class SummaryJUnitResultFormatter implements JUnitResultFormatter { + + /** + * Formatter for timings. + */ + private NumberFormat nf = NumberFormat.getInstance(); + + public SummaryJUnitResultFormatter() { + } + + /** + * The whole testsuite started. + */ + public void startTestSuite(JUnitTest suite) { + } + + /** + * Interface TestListener. + * + *

A new Test is started. + */ + public void startTest(Test t) { + } + + /** + * Interface TestListener. + * + *

A Test is finished. + */ + public void endTest(Test test) { + } + + /** + * Interface TestListener. + * + *

A Test failed. + */ + public void addFailure(Test test, Throwable t) { + } + + /** + * Interface TestListener. + * + *

An error occured while running the test. + */ + public void addError(Test test, Throwable t) { + } + + /** + * The whole testsuite ended. + */ + public void endTestSuite(JUnitTest suite) { + System.out.print("Tests run: "); + System.out.print(suite.runCount()); + System.out.print(", Failures: "); + System.out.print(suite.failureCount()); + System.out.print(", Errors: "); + System.out.print(suite.errorCount()); + System.out.print(", Time ellapsed: "); + System.out.print(nf.format(suite.getRunTime()/1000.0)); + System.out.println(" sec"); + } +} diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java new file mode 100644 index 000000000..8d2f0ce62 --- /dev/null +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java @@ -0,0 +1,235 @@ +/* + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 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", "Tomcat", 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 java.io.PrintWriter; +import java.io.StringWriter; +import java.text.CharacterIterator; +import java.text.NumberFormat; +import java.text.StringCharacterIterator; +import junit.framework.Test; +import junit.framework.TestCase; + +/** + * Prints XML output of the test to a specified Writer. + * + * @author Stefan Bodewig + */ + +public class XMLJUnitResultFormatter implements JUnitResultFormatter { + + /** + * OutputStream for XML output. + */ + private PrintWriter out; + /** + * Collects output during the test run. + */ + private StringBuffer results = new StringBuffer(); + /** + * platform independent line separator. + */ + private static String newLine = System.getProperty("line.separator"); + /** + * Formatter for timings. + */ + private NumberFormat nf = NumberFormat.getInstance(); + /** + * Timing helper. + */ + private long lastTestStart = 0; + + public XMLJUnitResultFormatter(PrintWriter out) { + this.out = out; + } + + /** + * The whole testsuite ended. + */ + public void endTestSuite(JUnitTest suite) { + out.println(""); + out.print(""); + out.print(results.toString()); + out.println(""); + out.flush(); + out.close(); + } + + /** + * The whole testsuite started. + */ + public void startTestSuite(JUnitTest suite) { + } + + /** + * Interface TestListener. + * + *

A new Test is started. + */ + public void startTest(Test t) { + lastTestStart = System.currentTimeMillis(); + } + + /** + * Interface TestListener. + * + *

A Test is finished. + */ + public void endTest(Test test) { + formatTestCaseOpenTag(test); + results.append(" "); + results.append(newLine); + } + + /** + * Interface TestListener. + * + *

A Test failed. + */ + public void addFailure(Test test, Throwable t) { + formatError("failure", test, t); + } + + /** + * Interface TestListener. + * + *

An error occured while running the test. + */ + public void addError(Test test, Throwable t) { + formatError("error", test, t); + } + + /** + * Translates <, & and > to corresponding entities. + */ + private String xmlEscape(String orig) { + if (orig == null) return ""; + StringBuffer temp = new StringBuffer(); + StringCharacterIterator sci = new StringCharacterIterator(orig); + for (char c = sci.first(); c != CharacterIterator.DONE; + c = sci.next()) { + + switch (c) { + case '<': + temp.append("<"); + break; + case '>': + temp.append(">"); + break; + case '&': + temp.append("&"); + break; + default: + temp.append(c); + break; + } + } + return temp.toString(); + } + + private void formatTestCaseOpenTag(Test test) { + results.append(" "); + results.append(newLine); + } + + private void formatError(String type, Test test, Throwable t) { + formatTestCaseOpenTag(test); + results.append(" <"); + results.append(type); + results.append(" message=\""); + results.append(xmlEscape(t.getMessage())); + results.append("\" type=\""); + results.append(t.getClass().getName()); + results.append("\">"); + results.append(newLine); + + results.append(""); + results.append(newLine); + + results.append(" "); + results.append(newLine); + + results.append(" "); + results.append(newLine); + } + + +} // XMLJUnitResultFormatter