Browse Source

Optional JUnit task.

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-ffa450edef68
master
Stefan Bodewig 25 years ago
parent
commit
b10787b4a7
8 changed files with 1275 additions and 0 deletions
  1. +17
    -0
      build.xml
  2. +1
    -0
      src/main/org/apache/tools/ant/taskdefs/defaults.properties
  3. +75
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitResultFormatter.java
  4. +292
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTask.java
  5. +202
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTest.java
  6. +325
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junit/JUnitTestRunner.java
  7. +128
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junit/SummaryJUnitResultFormatter.java
  8. +235
    -0
      src/main/org/apache/tools/ant/taskdefs/optional/junit/XMLJUnitResultFormatter.java

+ 17
- 0
build.xml View File

@@ -80,6 +80,7 @@
<exclude name="**/WLRun.java" unless="ejb.wls.present" />
<exclude name="**/WLStop.java" unless="ejb.wls.present" />
<exclude name="**/EjbJar.java" unless="ejb.build" />
<exclude name="**/junit/*" unless="junit.present" />
</javac>
<copydir src="${src.dir}" dest="${build.classes}">
@@ -266,6 +267,22 @@
<!-- Run testcase -->
<!-- =================================================================== -->
<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"
classname="junit.textui.TestRunner"
args="org.apache.tools.ant.AllJUnitTests"


+ 1
- 0
src/main/org/apache/tools/ant/taskdefs/defaults.properties View File

@@ -49,6 +49,7 @@ wlstop=org.apache.tools.ant.taskdefs.optional.ejb.WLStop
vssget=org.apache.tools.ant.taskdefs.optional.vss.MSVSSGET
ejbjar=org.apache.tools.ant.taskdefs.optional.ejb.EjbJar
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)
javadoc2=org.apache.tools.ant.taskdefs.Javadoc


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

@@ -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);
}

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

@@ -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);
}
}

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

@@ -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());
}

}

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

@@ -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

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

@@ -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");
}
}

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

@@ -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("&lt;");
break;
case '>':
temp.append("&gt;");
break;
case '&':
temp.append("&amp;");
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

Loading…
Cancel
Save