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 }