Submitted by: Thomas Haas <thomas.haas@softwired-inc.com> git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@267806 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -80,6 +80,7 @@ | |||||
| <exclude name="**/WLRun.java" unless="ejb.wls.present" /> | <exclude name="**/WLRun.java" unless="ejb.wls.present" /> | ||||
| <exclude name="**/WLStop.java" unless="ejb.wls.present" /> | <exclude name="**/WLStop.java" unless="ejb.wls.present" /> | ||||
| <exclude name="**/EjbJar.java" unless="ejb.build" /> | <exclude name="**/EjbJar.java" unless="ejb.build" /> | ||||
| <exclude name="**/junit/*" unless="junit.present" /> | |||||
| </javac> | </javac> | ||||
| <copydir src="${src.dir}" dest="${build.classes}"> | <copydir src="${src.dir}" dest="${build.classes}"> | ||||
| @@ -266,6 +267,22 @@ | |||||
| <!-- Run testcase --> | <!-- Run testcase --> | ||||
| <!-- =================================================================== --> | <!-- =================================================================== --> | ||||
| <target name="runtests" depends="compiletests" if="junit.present"> | <target name="runtests" depends="compiletests" if="junit.present"> | ||||
| <!-- | |||||
| This would make the buildprocess fail if using an Ant version | |||||
| without the junit task | |||||
| <junit defaultprintxml="false" defaultprintsummary="true" fork="on"> | |||||
| <classpath> | |||||
| <pathelement location="${lib.dir}/${name}.jar" /> | |||||
| <pathelement location="${build.tests}" /> | |||||
| <pathelement path="${classpath}" /> | |||||
| <pathelement path="${java.class.path}" /> | |||||
| </classpath> | |||||
| <test name="org.apache.tools.ant.AllJUnitTests" /> | |||||
| </junit> | |||||
| --> | |||||
| <java fork="yes" | <java fork="yes" | ||||
| classname="junit.textui.TestRunner" | classname="junit.textui.TestRunner" | ||||
| args="org.apache.tools.ant.AllJUnitTests" | args="org.apache.tools.ant.AllJUnitTests" | ||||
| @@ -49,6 +49,7 @@ wlstop=org.apache.tools.ant.taskdefs.optional.ejb.WLStop | |||||
| vssget=org.apache.tools.ant.taskdefs.optional.vss.MSVSSGET | vssget=org.apache.tools.ant.taskdefs.optional.vss.MSVSSGET | ||||
| ejbjar=org.apache.tools.ant.taskdefs.optional.ejb.EjbJar | ejbjar=org.apache.tools.ant.taskdefs.optional.ejb.EjbJar | ||||
| javacc=org.apache.tools.ant.taskdefs.optional.javacc.JavaCC | javacc=org.apache.tools.ant.taskdefs.optional.javacc.JavaCC | ||||
| junit=org.apache.tools.ant.taskdefs.optional.junit.JUnitTask | |||||
| # deprecated ant tasks (kept for back compatibility) | # deprecated ant tasks (kept for back compatibility) | ||||
| javadoc2=org.apache.tools.ant.taskdefs.Javadoc | javadoc2=org.apache.tools.ant.taskdefs.Javadoc | ||||
| @@ -0,0 +1,75 @@ | |||||
| /* | |||||
| * 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 | |||||
| * <http://www.apache.org/>. | |||||
| */ | |||||
| 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 <a href="mailto:stefan.bodewig@megabit.net">Stefan Bodewig</a> | |||||
| */ | |||||
| public interface JUnitResultFormatter extends TestListener { | |||||
| /** | |||||
| * The whole testsuite started. | |||||
| */ | |||||
| public void startTestSuite(JUnitTest suite); | |||||
| /** | |||||
| * The whole testsuite ended. | |||||
| */ | |||||
| public void endTestSuite(JUnitTest suite); | |||||
| } | |||||
| @@ -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 | |||||
| * <http://www.apache.org/>. | |||||
| */ | |||||
| 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. | |||||
| * | |||||
| * <p>JUnit is a framework to create unit test. It has been initially | |||||
| * created by Erich Gamma and Kent Beck. JUnit can be found at <a | |||||
| * href="http://www.xprogramming.com/software.htm">http://www.xprogramming.com/software.htm</a>. | |||||
| * | |||||
| * <p> This ant task runs a single TestCase. By default it spans a new | |||||
| * Java VM to prevent interferences between different testcases, | |||||
| * unless <code>fork</code> has been disabled. | |||||
| * | |||||
| * @author Thomas Haas | |||||
| */ | |||||
| public class JUnitTask extends Task { | |||||
| // <XXX> private final static int HALT_NOT = 1; | |||||
| // <XXX> private final static int HALT_IMMEDIATELY = 2; | |||||
| // <XXX> 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; | |||||
| // <XXX> private int haltOnError = HALT_AT_END; | |||||
| // <XXX> 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); | |||||
| // } | |||||
| // <XXX> 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 ; | |||||
| } | |||||
| // <XXX> 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); | |||||
| } | |||||
| } | |||||
| @@ -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 | |||||
| * <http://www.apache.org/>. | |||||
| */ | |||||
| 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<args.length; i++) { | |||||
| if (args[i] == null) continue; | |||||
| if (args[i].startsWith("haltOnError=")) { | |||||
| haltOnError = Project.toBoolean(args[i].substring(12)); | |||||
| } else if (args[i].startsWith("haltOnFailure=")) { | |||||
| haltOnFail = Project.toBoolean(args[i].substring(14)); | |||||
| } else if (args[i].startsWith("printSummary=")) { | |||||
| printSummary = Project.toBoolean(args[i].substring(13)); | |||||
| } else if (args[i].startsWith("printXML=")) { | |||||
| printXml = Project.toBoolean(args[i].substring(9)); | |||||
| } else if (args[i].startsWith("outfile=")) { | |||||
| outfile = args[i].substring(8); | |||||
| } | |||||
| } | |||||
| } | |||||
| public String[] getCommandline() { | |||||
| final Commandline result = new Commandline(); | |||||
| if (name != null && name.length() > 0) { | |||||
| result.setExecutable(name); | |||||
| } | |||||
| result.createArgument().setValue("exit=" + systemExit); | |||||
| result.createArgument().setValue("haltOnError=" + haltOnError); | |||||
| result.createArgument().setValue("haltOnFailure=" + haltOnFail); | |||||
| result.createArgument().setValue("printSummary=" + printSummary); | |||||
| result.createArgument().setValue("printXML=" + printXml); | |||||
| if (outfile != null && outfile.length() > 0) { | |||||
| result.createArgument().setValue("outfile=" + outfile); | |||||
| } | |||||
| return result.getCommandline(); | |||||
| } | |||||
| public void setCounts(long runs, long failures, long errors) { | |||||
| this.runs = runs; | |||||
| this.failures = failures; | |||||
| this.errors = errors; | |||||
| } | |||||
| public void setRunTime(long runTime) { | |||||
| this.runTime = runTime; | |||||
| } | |||||
| public long runCount() {return runs;} | |||||
| public long failureCount() {return failures;} | |||||
| public long errorCount() {return errors;} | |||||
| public long getRunTime() {return runTime;} | |||||
| public String toString() { | |||||
| return Commandline.toString(getCommandline()); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,325 @@ | |||||
| /* | |||||
| * 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 | |||||
| * <http://www.apache.org/>. | |||||
| */ | |||||
| 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. | |||||
| * | |||||
| * <p>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. | |||||
| * | |||||
| * <p>Otherwise 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@megabit.net">Stefan Bodewig</a> | |||||
| */ | |||||
| 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. | |||||
| * | |||||
| * <p>A new Test is started. | |||||
| */ | |||||
| public void startTest(Test t) { | |||||
| failed = false; | |||||
| } | |||||
| /** | |||||
| * Interface TestListener. | |||||
| * | |||||
| * <p>A Test is finished. | |||||
| */ | |||||
| public void endTest(Test test) { | |||||
| } | |||||
| /** | |||||
| * Interface TestListener. | |||||
| * | |||||
| * <p>A Test failed. | |||||
| */ | |||||
| public void addFailure(Test test, Throwable t) { | |||||
| failed = true; | |||||
| if (junitTest.getHaltonfailure()) { | |||||
| res.stop(); | |||||
| } | |||||
| } | |||||
| /** | |||||
| * Interface TestListener. | |||||
| * | |||||
| * <p>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<formatters.size(); i++) { | |||||
| ((JUnitResultFormatter)formatters.elementAt(i)).startTestSuite(junitTest); | |||||
| } | |||||
| } | |||||
| private void fireEndTestSuite() { | |||||
| for (int i=0; i<formatters.size(); i++) { | |||||
| ((JUnitResultFormatter)formatters.elementAt(i)).endTestSuite(junitTest); | |||||
| } | |||||
| } | |||||
| public void addFormatter(JUnitResultFormatter f) { | |||||
| formatters.addElement(f); | |||||
| } | |||||
| /** | |||||
| * Entry point for standalone (forked) mode. | |||||
| * | |||||
| * Parameters: testcaseclassname plus (up to) 6 parameters in the | |||||
| * format key=value. | |||||
| * | |||||
| * <table cols="3" border="1"> | |||||
| * <tr><th>key</th><th>description</th><th>default value</th></tr> | |||||
| * | |||||
| * <tr><td>exit</td><td>exit with System.exit after testcase is | |||||
| * complete?</td><td>true</td></tr> | |||||
| * | |||||
| * <tr><td>haltOnError</td><td>halt test on | |||||
| * errors?</td><td>false</td></tr> | |||||
| * | |||||
| * <tr><td>haltOnFailure</td><td>halt test on | |||||
| * failures?</td><td>false</td></tr> | |||||
| * | |||||
| * <tr><td>printSummary</td><td>print summary to System.out?</td> | |||||
| * <td>true</td></tr> | |||||
| * | |||||
| * <tr><td>printXML</td><td>generate XML report?</td> | |||||
| * <td>false</td></tr> | |||||
| * | |||||
| * <tr><td>outfile</td><td>where to print the XML report - a | |||||
| * filename</td> <td>System.out</td></tr> | |||||
| * | |||||
| * </table> | |||||
| */ | |||||
| 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 | |||||
| @@ -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 | |||||
| * <http://www.apache.org/>. | |||||
| */ | |||||
| 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 <a href="mailto:stefan.bodewig@megabit.net">Stefan Bodewig</a> | |||||
| */ | |||||
| 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. | |||||
| * | |||||
| * <p>A new Test is started. | |||||
| */ | |||||
| public void startTest(Test t) { | |||||
| } | |||||
| /** | |||||
| * Interface TestListener. | |||||
| * | |||||
| * <p>A Test is finished. | |||||
| */ | |||||
| public void endTest(Test test) { | |||||
| } | |||||
| /** | |||||
| * Interface TestListener. | |||||
| * | |||||
| * <p>A Test failed. | |||||
| */ | |||||
| public void addFailure(Test test, Throwable t) { | |||||
| } | |||||
| /** | |||||
| * Interface TestListener. | |||||
| * | |||||
| * <p>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"); | |||||
| } | |||||
| } | |||||
| @@ -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 | |||||
| * <http://www.apache.org/>. | |||||
| */ | |||||
| 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 <a href="mailto:stefan.bodewig@megabit.net">Stefan Bodewig</a> | |||||
| */ | |||||
| 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("<?xml version=\"1.0\"?>"); | |||||
| out.print("<testsuite name=\""); | |||||
| out.print(suite.getName()); | |||||
| out.print("\" tests=\""); | |||||
| out.print(suite.runCount()); | |||||
| out.print("\" failures=\""); | |||||
| out.print(suite.failureCount()); | |||||
| out.print("\" errors=\""); | |||||
| out.print(suite.errorCount()); | |||||
| out.print("\" time=\""); | |||||
| out.print(nf.format(suite.getRunTime()/1000.0)); | |||||
| out.println(" sec\">"); | |||||
| out.print(results.toString()); | |||||
| out.println("</testsuite>"); | |||||
| out.flush(); | |||||
| out.close(); | |||||
| } | |||||
| /** | |||||
| * The whole testsuite started. | |||||
| */ | |||||
| public void startTestSuite(JUnitTest suite) { | |||||
| } | |||||
| /** | |||||
| * Interface TestListener. | |||||
| * | |||||
| * <p>A new Test is started. | |||||
| */ | |||||
| public void startTest(Test t) { | |||||
| lastTestStart = System.currentTimeMillis(); | |||||
| } | |||||
| /** | |||||
| * Interface TestListener. | |||||
| * | |||||
| * <p>A Test is finished. | |||||
| */ | |||||
| public void endTest(Test test) { | |||||
| formatTestCaseOpenTag(test); | |||||
| results.append(" </testcase>"); | |||||
| results.append(newLine); | |||||
| } | |||||
| /** | |||||
| * Interface TestListener. | |||||
| * | |||||
| * <p>A Test failed. | |||||
| */ | |||||
| public void addFailure(Test test, Throwable t) { | |||||
| formatError("failure", test, t); | |||||
| } | |||||
| /** | |||||
| * Interface TestListener. | |||||
| * | |||||
| * <p>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(" <testcase"); | |||||
| if (test != null && test instanceof TestCase) { | |||||
| results.append(" name=\""); | |||||
| results.append(((TestCase) test).name()); | |||||
| results.append("\""); | |||||
| } | |||||
| results.append(" time=\""); | |||||
| results.append(nf.format((System.currentTimeMillis()-lastTestStart) | |||||
| / 1000.0)); | |||||
| 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("<![CDATA["); | |||||
| results.append(newLine); | |||||
| StringWriter swr = new StringWriter(); | |||||
| t.printStackTrace(new PrintWriter(swr, true)); | |||||
| results.append(swr.toString()); | |||||
| results.append("]]>"); | |||||
| results.append(newLine); | |||||
| results.append(" </"); | |||||
| results.append(type); | |||||
| results.append(">"); | |||||
| results.append(newLine); | |||||
| results.append(" </testcase>"); | |||||
| results.append(newLine); | |||||
| } | |||||
| } // XMLJUnitResultFormatter | |||||