001 package junit.framework;
002
003 import java.util.ArrayList;
004 import java.util.Collections;
005 import java.util.Enumeration;
006 import java.util.List;
007
008 /**
009 * A <code>TestResult</code> collects the results of executing
010 * a test case. It is an instance of the Collecting Parameter pattern.
011 * The test framework distinguishes between <i>failures</i> and <i>errors</i>.
012 * A failure is anticipated and checked for with assertions. Errors are
013 * unanticipated problems like an {@link ArrayIndexOutOfBoundsException}.
014 *
015 * @see Test
016 */
017 public class TestResult {
018 protected List<TestFailure> fFailures;
019 protected List<TestFailure> fErrors;
020 protected List<TestListener> fListeners;
021 protected int fRunTests;
022 private boolean fStop;
023
024 public TestResult() {
025 fFailures = new ArrayList<TestFailure>();
026 fErrors = new ArrayList<TestFailure>();
027 fListeners = new ArrayList<TestListener>();
028 fRunTests = 0;
029 fStop = false;
030 }
031
032 /**
033 * Adds an error to the list of errors. The passed in exception
034 * caused the error.
035 */
036 public synchronized void addError(Test test, Throwable e) {
037 fErrors.add(new TestFailure(test, e));
038 for (TestListener each : cloneListeners()) {
039 each.addError(test, e);
040 }
041 }
042
043 /**
044 * Adds a failure to the list of failures. The passed in exception
045 * caused the failure.
046 */
047 public synchronized void addFailure(Test test, AssertionFailedError e) {
048 fFailures.add(new TestFailure(test, e));
049 for (TestListener each : cloneListeners()) {
050 each.addFailure(test, e);
051 }
052 }
053
054 /**
055 * Registers a TestListener.
056 */
057 public synchronized void addListener(TestListener listener) {
058 fListeners.add(listener);
059 }
060
061 /**
062 * Unregisters a TestListener.
063 */
064 public synchronized void removeListener(TestListener listener) {
065 fListeners.remove(listener);
066 }
067
068 /**
069 * Returns a copy of the listeners.
070 */
071 private synchronized List<TestListener> cloneListeners() {
072 List<TestListener> result = new ArrayList<TestListener>();
073 result.addAll(fListeners);
074 return result;
075 }
076
077 /**
078 * Informs the result that a test was completed.
079 */
080 public void endTest(Test test) {
081 for (TestListener each : cloneListeners()) {
082 each.endTest(test);
083 }
084 }
085
086 /**
087 * Gets the number of detected errors.
088 */
089 public synchronized int errorCount() {
090 return fErrors.size();
091 }
092
093 /**
094 * Returns an Enumeration for the errors.
095 */
096 public synchronized Enumeration<TestFailure> errors() {
097 return Collections.enumeration(fErrors);
098 }
099
100
101 /**
102 * Gets the number of detected failures.
103 */
104 public synchronized int failureCount() {
105 return fFailures.size();
106 }
107
108 /**
109 * Returns an Enumeration for the failures.
110 */
111 public synchronized Enumeration<TestFailure> failures() {
112 return Collections.enumeration(fFailures);
113 }
114
115 /**
116 * Runs a TestCase.
117 */
118 protected void run(final TestCase test) {
119 startTest(test);
120 Protectable p = new Protectable() {
121 public void protect() throws Throwable {
122 test.runBare();
123 }
124 };
125 runProtected(test, p);
126
127 endTest(test);
128 }
129
130 /**
131 * Gets the number of run tests.
132 */
133 public synchronized int runCount() {
134 return fRunTests;
135 }
136
137 /**
138 * Runs a TestCase.
139 */
140 public void runProtected(final Test test, Protectable p) {
141 try {
142 p.protect();
143 } catch (AssertionFailedError e) {
144 addFailure(test, e);
145 } catch (ThreadDeath e) { // don't catch ThreadDeath by accident
146 throw e;
147 } catch (Throwable e) {
148 addError(test, e);
149 }
150 }
151
152 /**
153 * Checks whether the test run should stop.
154 */
155 public synchronized boolean shouldStop() {
156 return fStop;
157 }
158
159 /**
160 * Informs the result that a test will be started.
161 */
162 public void startTest(Test test) {
163 final int count = test.countTestCases();
164 synchronized (this) {
165 fRunTests += count;
166 }
167 for (TestListener each : cloneListeners()) {
168 each.startTest(test);
169 }
170 }
171
172 /**
173 * Marks that the test run should stop.
174 */
175 public synchronized void stop() {
176 fStop = true;
177 }
178
179 /**
180 * Returns whether the entire test was successful or not.
181 */
182 public synchronized boolean wasSuccessful() {
183 return failureCount() == 0 && errorCount() == 0;
184 }
185 }