- Added TestSummary (TestResult was better but is conflicting with JUnit) which sole purpose is to provide a helpful summary of the sequence to listeners. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@271124 13f79535-47bb-0310-9956-ffa450edef68master
@@ -116,19 +116,24 @@ public class Server { | |||||
} | } | ||||
/** start a server to the specified port */ | /** start a server to the specified port */ | ||||
public void start() { | |||||
try { | |||||
start(false); | |||||
} catch (InterruptedException e){ | |||||
} | |||||
} | |||||
/** start a server to the specified port and wait for end */ | |||||
public void start(boolean flag) throws InterruptedException { | |||||
Worker worker = new Worker(); | |||||
worker.start(); | |||||
if (flag){ | |||||
worker.join(); | |||||
public void start(boolean loop) throws IOException { | |||||
server = new ServerSocket(port); | |||||
while (server != null) { | |||||
client = server.accept(); | |||||
messenger = new Messenger(client.getInputStream(), client.getOutputStream()); | |||||
TestRunEvent evt = null; | |||||
try { | |||||
while ( (evt = messenger.read()) != null ) { | |||||
dispatcher.dispatchEvent(evt); | |||||
} | |||||
} catch (Exception e){ | |||||
e.printStackTrace(); | |||||
//@fixme this stacktrace might be normal when closing | |||||
// the socket. So decompose the above in distinct steps | |||||
} | |||||
if (!loop){ | |||||
break; | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -169,26 +174,4 @@ public class Server { | |||||
} catch (IOException e) { | } catch (IOException e) { | ||||
} | } | ||||
} | } | ||||
//----- | |||||
private class Worker extends Thread { | |||||
public void run() { | |||||
try { | |||||
server = new ServerSocket(port); | |||||
client = server.accept(); | |||||
messenger = new Messenger(client.getInputStream(), client.getOutputStream()); | |||||
TestRunEvent evt = null; | |||||
while ( (evt = messenger.read()) != null ) { | |||||
dispatcher.dispatchEvent(evt); | |||||
} | |||||
} catch (Exception e) { | |||||
//@fixme this stacktrace might be normal when closing | |||||
// the socket. So decompose the above in distinct steps | |||||
} finally { | |||||
cancel(); | |||||
shutdown(); | |||||
} | |||||
} | |||||
} | |||||
} | } |
@@ -1,95 +0,0 @@ | |||||
/* | |||||
* The Apache Software License, Version 1.1 | |||||
* | |||||
* Copyright (c) 2002 The Apache Software Foundation. All rights | |||||
* reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* | |||||
* 1. Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in | |||||
* the documentation and/or other materials provided with the | |||||
* distribution. | |||||
* | |||||
* 3. The end-user documentation included with the redistribution, if | |||||
* any, must include the following acknowlegement: | |||||
* "This product includes software developed by the | |||||
* Apache Software Foundation (http://www.apache.org/)." | |||||
* Alternately, this acknowlegement may appear in the software itself, | |||||
* if and wherever such third-party acknowlegements normally appear. | |||||
* | |||||
* 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||||
* Foundation" must not be used to endorse or promote products derived | |||||
* from this software without prior written permission. For written | |||||
* permission, please contact apache@apache.org. | |||||
* | |||||
* 5. Products derived from this software may not be called "Apache" | |||||
* nor may "Apache" appear in their names without prior written | |||||
* permission of the Apache Group. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
* SUCH DAMAGE. | |||||
* ==================================================================== | |||||
* | |||||
* This software consists of voluntary contributions made by many | |||||
* individuals on behalf of the Apache Software Foundation. For more | |||||
* information on the Apache Software Foundation, please see | |||||
* <http://www.apache.org/>. | |||||
*/ | |||||
package org.apache.tools.ant.taskdefs.optional.rjunit.remote; | |||||
import java.io.ByteArrayInputStream; | |||||
import java.io.ByteArrayOutputStream; | |||||
import java.io.ObjectInputStream; | |||||
import java.io.ObjectOutputStream; | |||||
/** | |||||
* A set of helper methods related to sockets. | |||||
* | |||||
* @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a> | |||||
*/ | |||||
public class SocketUtil { | |||||
/** | |||||
* Helper method to deserialize an object | |||||
* @param bytes the binary data representing the serialized object. | |||||
* @return the deserialized object. | |||||
* @throws Exception a generic exception if an error occurs when | |||||
* deserializing the object. | |||||
*/ | |||||
public static Object deserialize(byte[] bytes) throws Exception { | |||||
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes)); | |||||
return ois.readObject(); | |||||
} | |||||
/** | |||||
* Helper method to serialize an object | |||||
* @param o the object to serialize. | |||||
* @return the binary data representing the serialized object. | |||||
* @throws Exception a generic exception if an error occurs when | |||||
* serializing the object. | |||||
*/ | |||||
public static byte[] serialize(Object o) throws Exception { | |||||
ByteArrayOutputStream out = new ByteArrayOutputStream(); | |||||
ObjectOutputStream oos = new ObjectOutputStream(out); | |||||
oos.writeObject(o); | |||||
oos.close(); | |||||
return out.toByteArray(); | |||||
} | |||||
} |
@@ -59,6 +59,9 @@ import java.util.Properties; | |||||
import org.apache.tools.ant.util.StringUtils; | import org.apache.tools.ant.util.StringUtils; | ||||
/** | /** | ||||
* Provide the basic events to be used during the tests. | |||||
* This is not very extensible but since the events should be somewhat | |||||
* limited, for now this is better to do it like this. | |||||
* | * | ||||
* @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a> | * @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a> | ||||
*/ | */ | ||||
@@ -81,7 +84,7 @@ public class TestRunEvent extends EventObject { | |||||
/** the type of event */ | /** the type of event */ | ||||
private int type = -1; | private int type = -1; | ||||
/** timestamp for all tests */ | |||||
/** timestamp for all events */ | |||||
private long timestamp = System.currentTimeMillis(); | private long timestamp = System.currentTimeMillis(); | ||||
/** name of testcase(method name) or testsuite (classname) */ | /** name of testcase(method name) or testsuite (classname) */ | ||||
@@ -93,19 +96,28 @@ public class TestRunEvent extends EventObject { | |||||
/** properties for end of testrun */ | /** properties for end of testrun */ | ||||
private Properties props; | private Properties props; | ||||
/** handy result for each end of sequence */ | |||||
private TestSummary result; | |||||
public TestRunEvent(Integer id, int type){ | public TestRunEvent(Integer id, int type){ | ||||
super(id); | super(id); | ||||
this.type = type; | this.type = type; | ||||
} | } | ||||
public TestRunEvent(Integer id, int type, String name, TestSummary result){ | |||||
this(id, type, name); | |||||
this.result = result; | |||||
} | |||||
public TestRunEvent(Integer id, int type, String name){ | public TestRunEvent(Integer id, int type, String name){ | ||||
this(id, type); | this(id, type); | ||||
this.name = name; | this.name = name; | ||||
} | } | ||||
public TestRunEvent(Integer id, int type, Properties props){ | |||||
public TestRunEvent(Integer id, int type, Properties props, TestSummary result){ | |||||
this(id, type); | this(id, type); | ||||
this.props = props; | this.props = props; | ||||
this.result = result; | |||||
} | } | ||||
public TestRunEvent(Integer id, int type, String name, Throwable t){ | public TestRunEvent(Integer id, int type, String name, Throwable t){ | ||||
@@ -145,6 +157,10 @@ public class TestRunEvent extends EventObject { | |||||
return name; | return name; | ||||
} | } | ||||
public TestSummary getSummary(){ | |||||
return result; | |||||
} | |||||
public String getStackTrace(){ | public String getStackTrace(){ | ||||
return stacktrace; | return stacktrace; | ||||
} | } | ||||
@@ -160,7 +176,8 @@ public class TestRunEvent extends EventObject { | |||||
(timestamp == other.timestamp) && | (timestamp == other.timestamp) && | ||||
( name == null ? other.name == null : name.equals(other.name) ) && | ( name == null ? other.name == null : name.equals(other.name) ) && | ||||
( stacktrace == null ? other.stacktrace == null : stacktrace.equals(other.stacktrace) ) && | ( stacktrace == null ? other.stacktrace == null : stacktrace.equals(other.stacktrace) ) && | ||||
( props == null ? other.props == null : props.equals(other.props) ) ) ; | |||||
( props == null ? other.props == null : props.equals(other.props) ) && | |||||
( result == null ? other.result == null : result.equals(other.result) ) ); | |||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
@@ -62,6 +62,11 @@ import java.util.Properties; | |||||
import java.util.StringTokenizer; | import java.util.StringTokenizer; | ||||
import java.util.Vector; | import java.util.Vector; | ||||
import java.util.Random; | import java.util.Random; | ||||
import java.util.Map; | |||||
import java.util.HashMap; | |||||
import java.util.ArrayList; | |||||
import java.util.Collection; | |||||
import java.util.Iterator; | |||||
import junit.framework.AssertionFailedError; | import junit.framework.AssertionFailedError; | ||||
import junit.framework.Test; | import junit.framework.Test; | ||||
@@ -71,6 +76,8 @@ import junit.framework.TestResult; | |||||
import junit.framework.TestSuite; | import junit.framework.TestSuite; | ||||
import org.apache.tools.ant.taskdefs.optional.rjunit.JUnitHelper; | import org.apache.tools.ant.taskdefs.optional.rjunit.JUnitHelper; | ||||
import org.apache.tools.ant.taskdefs.optional.rjunit.formatter.Formatter; | |||||
import org.apache.tools.ant.taskdefs.optional.rjunit.formatter.PlainFormatter; | |||||
import org.apache.tools.ant.util.StringUtils; | import org.apache.tools.ant.util.StringUtils; | ||||
/** | /** | ||||
@@ -95,10 +102,11 @@ public class TestRunner implements TestListener { | |||||
/** port to connect to */ | /** port to connect to */ | ||||
private int port = -1; | private int port = -1; | ||||
/** handy debug flag */ | |||||
private boolean debug = false; | private boolean debug = false; | ||||
/** the list of test class names to run */ | /** the list of test class names to run */ | ||||
private Vector testClassNames = new Vector(); | |||||
private final ArrayList testClassNames = new ArrayList(); | |||||
/** result of the current test */ | /** result of the current test */ | ||||
private TestResult testResult; | private TestResult testResult; | ||||
@@ -109,8 +117,14 @@ public class TestRunner implements TestListener { | |||||
/** writer to send message to the server */ | /** writer to send message to the server */ | ||||
private Messenger messenger; | private Messenger messenger; | ||||
/** helpful formatter to debug events directly here */ | |||||
private final Formatter debugFormatter = new PlainFormatter(); | |||||
/** bean constructor */ | /** bean constructor */ | ||||
public TestRunner() { | public TestRunner() { | ||||
Properties props = new Properties(); | |||||
props.setProperty("file", "rjunit-client-debug.log"); | |||||
debugFormatter.init(props); | |||||
} | } | ||||
/** | /** | ||||
@@ -142,7 +156,7 @@ public class TestRunner implements TestListener { | |||||
* @param classname the class name of the test to run. | * @param classname the class name of the test to run. | ||||
*/ | */ | ||||
public void addTestClassName(String classname) { | public void addTestClassName(String classname) { | ||||
testClassNames.addElement(classname); | |||||
testClassNames.add(classname); | |||||
} | } | ||||
/** | /** | ||||
@@ -265,16 +279,16 @@ public class TestRunner implements TestListener { | |||||
* @throws Exception a generic exception that can be thrown while | * @throws Exception a generic exception that can be thrown while | ||||
* instantiating a test case. | * instantiating a test case. | ||||
*/ | */ | ||||
protected Test[] getSuites() throws Exception { | |||||
protected Map getSuites() throws Exception { | |||||
final int count = testClassNames.size(); | final int count = testClassNames.size(); | ||||
log("Extracting testcases from " + count + " classnames..."); | log("Extracting testcases from " + count + " classnames..."); | ||||
final Vector suites = new Vector(count); | |||||
final Map suites = new HashMap(); | |||||
for (int i = 0; i < count; i++) { | for (int i = 0; i < count; i++) { | ||||
String classname = (String) testClassNames.elementAt(i); | |||||
String classname = (String) testClassNames.get(i); | |||||
try { | try { | ||||
Test test = JUnitHelper.getTest(null, classname); | Test test = JUnitHelper.getTest(null, classname); | ||||
if (test != null) { | if (test != null) { | ||||
suites.addElement(test); | |||||
suites.put(classname, test); | |||||
} | } | ||||
} catch (Exception e) { | } catch (Exception e) { | ||||
// notify log error instead ? | // notify log error instead ? | ||||
@@ -283,9 +297,7 @@ public class TestRunner implements TestListener { | |||||
} | } | ||||
} | } | ||||
log("Extracted " + suites.size() + " testcases."); | log("Extracted " + suites.size() + " testcases."); | ||||
Test[] array = new Test[suites.size()]; | |||||
suites.copyInto(array); | |||||
return array; | |||||
return suites; | |||||
} | } | ||||
/** | /** | ||||
@@ -293,41 +305,75 @@ public class TestRunner implements TestListener { | |||||
*/ | */ | ||||
private void runTests() throws Exception { | private void runTests() throws Exception { | ||||
Test[] suites = getSuites(); | |||||
Map suites = getSuites(); | |||||
// count all testMethods and inform TestRunListeners | // count all testMethods and inform TestRunListeners | ||||
int count = countTests(suites); | |||||
int count = countTests(suites.values()); | |||||
log("Total tests to run: " + count); | log("Total tests to run: " + count); | ||||
fireEvent(new TestRunEvent(id, TestRunEvent.RUN_STARTED)); | |||||
long startTime = System.currentTimeMillis(); | |||||
for (int i = 0; i < suites.length; i++) { | |||||
String name = suites[i].getClass().getName(); | |||||
if (suites[i] instanceof TestCase) { | |||||
suites[i] = new TestSuite(name); | |||||
TestRunEvent evt = new TestRunEvent(id, TestRunEvent.RUN_STARTED); | |||||
if (debug){ | |||||
debugFormatter.onRunStarted(evt); | |||||
} | |||||
fireEvent(evt); | |||||
TestSummary runSummary = new TestSummary(); | |||||
runSummary.start(testResult); | |||||
for (Iterator it = suites.entrySet().iterator(); it.hasNext(); ) { | |||||
Map.Entry entry = (Map.Entry)it.next(); | |||||
String name = (String)entry.getKey(); | |||||
Test test = (Test)entry.getValue(); | |||||
if (test instanceof TestCase) { | |||||
test = new TestSuite(name); | |||||
} | } | ||||
log("running suite: " + suites[i]); | |||||
fireEvent(new TestRunEvent(id, TestRunEvent.SUITE_STARTED, name)); | |||||
suites[i].run(testResult); | |||||
fireEvent(new TestRunEvent(id, TestRunEvent.SUITE_ENDED, name)); | |||||
runTest(test, name); | |||||
} | } | ||||
runSummary.stop(testResult); | |||||
// inform TestRunListeners of test end | // inform TestRunListeners of test end | ||||
long elapsedTime = System.currentTimeMillis() - startTime; | |||||
if (testResult == null || testResult.shouldStop()) { | |||||
fireEvent(new TestRunEvent(id, TestRunEvent.RUN_STOPPED, System.getProperties())); | |||||
} else { | |||||
fireEvent(new TestRunEvent(id, TestRunEvent.RUN_ENDED, System.getProperties())); | |||||
int type = (testResult == null || testResult.shouldStop()) ? | |||||
TestRunEvent.RUN_STOPPED : TestRunEvent.RUN_ENDED; | |||||
evt = new TestRunEvent(id, type, System.getProperties(), runSummary); | |||||
if (debug){ | |||||
debugFormatter.onRunEnded(evt); | |||||
} | } | ||||
log("Finished after " + elapsedTime + "ms"); | |||||
fireEvent(evt); | |||||
log("Finished after " + runSummary.elapsedTime() + "ms"); | |||||
shutDown(); | shutDown(); | ||||
} | } | ||||
/** count the number of test methods in all tests */ | |||||
private final int countTests(Test[] tests) { | |||||
/** | |||||
* run a single suite and dispatch its results. | |||||
* @param test the instance of the testsuite to run. | |||||
* @param name the name of the testsuite (classname) | |||||
*/ | |||||
private void runTest(Test test, String name){ | |||||
TestRunEvent evt = new TestRunEvent(id, TestRunEvent.SUITE_STARTED, name); | |||||
if (debug){ | |||||
debugFormatter.onSuiteStarted(evt); | |||||
} | |||||
fireEvent(evt); | |||||
TestSummary suiteSummary = new TestSummary(); | |||||
suiteSummary.start(testResult); | |||||
try { | |||||
test.run(testResult); | |||||
} finally { | |||||
suiteSummary.stop(testResult); | |||||
evt = new TestRunEvent(id, TestRunEvent.SUITE_ENDED, name, suiteSummary); | |||||
if (debug){ | |||||
debugFormatter.onSuiteEnded(evt); | |||||
} | |||||
fireEvent(evt); | |||||
} | |||||
} | |||||
/** | |||||
* count the number of test methods in all tests | |||||
*/ | |||||
private final int countTests(Collection tests) { | |||||
int count = 0; | int count = 0; | ||||
for (int i = 0; i < tests.length; i++) { | |||||
count = count + tests[i].countTestCases(); | |||||
for (Iterator it = tests.iterator(); it.hasNext(); ) { | |||||
Test test = (Test)it.next(); | |||||
count = count + test.countTestCases(); | |||||
} | } | ||||
return count; | return count; | ||||
} | } | ||||
@@ -383,14 +429,20 @@ public class TestRunner implements TestListener { | |||||
public void startTest(Test test) { | public void startTest(Test test) { | ||||
String testName = test.toString(); | String testName = test.toString(); | ||||
log("starting test: " + test); | |||||
fireEvent(new TestRunEvent(id, TestRunEvent.TEST_STARTED, testName)); | |||||
TestRunEvent evt = new TestRunEvent(id, TestRunEvent.TEST_STARTED, testName); | |||||
if (debug){ | |||||
debugFormatter.onTestStarted(evt); | |||||
} | |||||
fireEvent(evt); | |||||
} | } | ||||
public void addError(Test test, Throwable t) { | public void addError(Test test, Throwable t) { | ||||
log("Adding error for test: " + test); | |||||
String testName = test.toString(); | String testName = test.toString(); | ||||
fireEvent(new TestRunEvent(id, TestRunEvent.TEST_ERROR, testName, t)); | |||||
TestRunEvent evt = new TestRunEvent(id, TestRunEvent.TEST_ERROR, testName, t); | |||||
if (debug){ | |||||
debugFormatter.onTestError(evt); | |||||
} | |||||
fireEvent(evt); | |||||
} | } | ||||
/** | /** | ||||
@@ -406,15 +458,21 @@ public class TestRunner implements TestListener { | |||||
* @see addFailure(Test, AssertionFailedError) | * @see addFailure(Test, AssertionFailedError) | ||||
*/ | */ | ||||
public void addFailure(Test test, Throwable t) { | public void addFailure(Test test, Throwable t) { | ||||
log("Adding failure for test: " + test); | |||||
String testName = test.toString(); | String testName = test.toString(); | ||||
fireEvent(new TestRunEvent(id, TestRunEvent.TEST_FAILURE, testName, t)); | |||||
TestRunEvent evt = new TestRunEvent(id, TestRunEvent.TEST_FAILURE, testName, t); | |||||
if (debug){ | |||||
debugFormatter.onTestFailure(evt); | |||||
} | |||||
fireEvent(evt); | |||||
} | } | ||||
public void endTest(Test test) { | public void endTest(Test test) { | ||||
log("Ending test: " + test); | |||||
String testName = test.toString(); | String testName = test.toString(); | ||||
fireEvent(new TestRunEvent(id, TestRunEvent.TEST_ENDED, testName)); | |||||
TestRunEvent evt = new TestRunEvent(id, TestRunEvent.TEST_ENDED, testName); | |||||
if (debug){ | |||||
debugFormatter.onTestEnded(evt); | |||||
} | |||||
fireEvent(evt); | |||||
} | } | ||||
public void log(String msg) { | public void log(String msg) { | ||||
@@ -0,0 +1,177 @@ | |||||
/* | |||||
* The Apache Software License, Version 1.1 | |||||
* | |||||
* Copyright (c) 2002 The Apache Software Foundation. All rights | |||||
* reserved. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* | |||||
* 1. Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in | |||||
* the documentation and/or other materials provided with the | |||||
* distribution. | |||||
* | |||||
* 3. The end-user documentation included with the redistribution, if | |||||
* any, must include the following acknowlegement: | |||||
* "This product includes software developed by the | |||||
* Apache Software Foundation (http://www.apache.org/)." | |||||
* Alternately, this acknowlegement may appear in the software itself, | |||||
* if and wherever such third-party acknowlegements normally appear. | |||||
* | |||||
* 4. The names "The Jakarta Project", "Ant", and "Apache Software | |||||
* Foundation" must not be used to endorse or promote products derived | |||||
* from this software without prior written permission. For written | |||||
* permission, please contact apache@apache.org. | |||||
* | |||||
* 5. Products derived from this software may not be called "Apache" | |||||
* nor may "Apache" appear in their names without prior written | |||||
* permission of the Apache Group. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED | |||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||||
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR | |||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | |||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
* SUCH DAMAGE. | |||||
* ==================================================================== | |||||
* | |||||
* This software consists of voluntary contributions made by many | |||||
* individuals on behalf of the Apache Software Foundation. For more | |||||
* information on the Apache Software Foundation, please see | |||||
* <http://www.apache.org/>. | |||||
*/ | |||||
package org.apache.tools.ant.taskdefs.optional.rjunit.remote; | |||||
import java.io.Serializable; | |||||
import junit.framework.AssertionFailedError; | |||||
import junit.framework.Test; | |||||
import junit.framework.TestListener; | |||||
import junit.framework.TestResult; | |||||
/** | |||||
* A helpful test summary that is somewhat similar to <tt>TestResult</tt>. | |||||
* Here the difference is that this test summary should register to | |||||
* the test result the time you wan to collect information. | |||||
* | |||||
* @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a> | |||||
*/ | |||||
public final class TestSummary implements Serializable, TestListener { | |||||
/** time elapsed during tests run in ms */ | |||||
private long elapsedTime; | |||||
/** number of errors */ | |||||
private int errorCount; | |||||
/** number of successes */ | |||||
private int successCount; | |||||
/** number of failures */ | |||||
private int failureCount; | |||||
/** number of runs */ | |||||
private int runCount; | |||||
private transient String toString; | |||||
/** bean constructor */ | |||||
public TestSummary() { | |||||
} | |||||
/** | |||||
* @return the number of errors that occurred in this test. | |||||
*/ | |||||
public int errorCount() { | |||||
return errorCount; | |||||
} | |||||
/** | |||||
* @return the number of successes that occurred in this test. | |||||
*/ | |||||
public int successCount() { | |||||
return successCount; | |||||
} | |||||
/** | |||||
* @return the number of failures that occurred in this test. | |||||
*/ | |||||
public int failureCount() { | |||||
return failureCount; | |||||
} | |||||
/** | |||||
* @return the number of runs that occurred in this test. | |||||
* a run is the sum of failures + errors + successes. | |||||
*/ | |||||
public int runCount() { | |||||
return runCount; | |||||
} | |||||
/** | |||||
* @return the elapsed time in ms | |||||
*/ | |||||
public long elapsedTime() { | |||||
return elapsedTime; | |||||
} | |||||
// | |||||
/** | |||||
* register to the <tt>TestResult</tt> and starts the time counter. | |||||
* @param result the instance to register to. | |||||
* @see #stop() | |||||
*/ | |||||
public void start(TestResult result){ | |||||
elapsedTime = System.currentTimeMillis(); | |||||
result.addListener(this); | |||||
} | |||||
/** | |||||
* unregister from the <tt>TestResult</tt> and stops the time counter. | |||||
* @param result the instance to unregister from. | |||||
* @see #start() | |||||
*/ | |||||
public void stop(TestResult result){ | |||||
elapsedTime = System.currentTimeMillis() - elapsedTime; | |||||
result.removeListener(this); | |||||
} | |||||
// test listener implementation | |||||
public void addError(Test test, Throwable throwable) { | |||||
errorCount++; | |||||
} | |||||
public void addFailure(Test test, AssertionFailedError error) { | |||||
failureCount++; | |||||
} | |||||
public void endTest(Test test) { | |||||
successCount++; | |||||
} | |||||
public void startTest(Test test) { | |||||
runCount++; | |||||
} | |||||
public String toString(){ | |||||
StringBuffer buf = new StringBuffer(); | |||||
buf.append("run: ").append(runCount); | |||||
buf.append(" success: ").append(successCount); | |||||
buf.append(" failures: ").append(failureCount); | |||||
buf.append(" errors: ").append(errorCount); | |||||
buf.append(" elapsed: ").append(elapsedTime); | |||||
return buf.toString(); | |||||
} | |||||
} |