1 <?php
2 require_once 'PHPUnit/Framework/TestResult.php';
3 require_once 'PHPUnit/Framework/TestListener.php';
4
5 6 7
8 9 10
11 define('TEST_FAILURE', -1);
12 13 14
15 define('TEST_ERROR', 0);
16 17 18
19 define('TEST_SUCCESS', 1);
20 21 22
23 define('TEST_INCOMPLETE', 2);
24
25
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
42 class SapphireTestReporter implements PHPUnit_Framework_TestListener {
43 44 45 46
47 protected $suiteResults;
48 49 50 51
52 protected $currentSuite;
53 54 55 56
57 protected $currentTest;
58 59 60 61
62 protected $hasTimer;
63 64 65 66
67 protected $timer;
68
69 protected $startTestTime;
70
71 72 73
74 protected $testSpeeds = array();
75
76 77 78 79 80 81 82
83 public function __construct() {
84 @include_once 'Benchmark/Timer.php';
85 if(class_exists('Benchmark_Timer')) {
86 $this->timer = new Benchmark_Timer();
87 $this->hasTimer = true;
88 } else {
89 $this->hasTimer = false;
90 }
91
92 $this->suiteResults = array(
93 'suites' => array(),
94 'hasTimer' => $this->hasTimer,
95 'totalTests' => 0
96 );
97 }
98
99 100 101 102 103 104
105 public function getSuiteResults() {
106 return $this->suiteResults;
107 }
108
109 110 111 112 113 114 115 116
117 public function startTestSuite( PHPUnit_Framework_TestSuite $suite) {
118 if(strlen($suite->getName())) {
119 $this->currentSuite = array(
120 'suite' => $suite,
121 'tests' => array(),
122 'errors' => 0,
123 'failures' => 0,
124 'incomplete' => 0);
125 }
126 }
127
128 129 130 131 132 133 134 135
136 public function startTest(PHPUnit_Framework_Test $test) {
137 $this->startTestTime = microtime(true);
138
139 if($test instanceof PHPUnit_Framework_TestCase) {
140 $this->currentTest = array(
141 'name' => preg_replace('(\(.*\))', '', $test->toString()),
142 'timeElapsed' => 0,
143 'status' => TEST_SUCCESS,
144 'message' => '',
145 'exception' => NULL,
146 'uid' => md5(microtime())
147 );
148 if($this->hasTimer) $this->timer->start();
149 }
150 }
151
152 153 154 155 156 157 158 159 160
161 public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) {
162 $this->currentSuite['failures']++;
163 $this->currentTest['status'] = TEST_FAILURE;
164 $this->currentTest['message'] = $e->toString();
165 $this->currentTest['exception'] = $this->getTestException($test, $e);
166 $this->currentTest['trace'] = $e->getTrace();
167 }
168
169 170 171 172 173 174 175 176 177
178 public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) {
179 $this->currentSuite['errors']++;
180 $this->currentTest['status'] = TEST_ERROR;
181 $this->currentTest['message'] = $e->getMessage();
182 $this->currentTest['exception'] = $this->getTestException($test, $e);
183 $this->currentTest['trace'] = $e->getTrace();
184 }
185
186 187 188 189 190 191 192 193 194
195 public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) {
196 $this->currentSuite['incomplete']++;
197 $this->currentTest['status'] = TEST_INCOMPLETE;
198 $this->currentTest['message'] = $e->toString();
199 $this->currentTest['exception'] = $this->getTestException($test, $e);
200 $this->currentTest['trace'] = $e->getTrace();
201 }
202
203 204 205 206 207 208
209 public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) {
210
211 }
212
213 214 215 216 217 218 219 220
221 public function endTest( PHPUnit_Framework_Test $test, $time) {
222 $testDuration = microtime(true) - $this->startTestTime;
223 $this->testSpeeds[$this->currentSuite['suite']->getName() . '.' . $this->currentTest['name']] = $testDuration;
224
225 if($this->hasTimer) {
226 $this->timer->stop();
227 $this->currentTest['timeElapsed'] = $this->timer->timeElapsed();
228 }
229 array_push($this->currentSuite['tests'], $this->currentTest);
230 }
231
232 233 234 235 236 237 238
239 public function endTestSuite( PHPUnit_Framework_TestSuite $suite) {
240 if(strlen($suite->getName())) {
241 array_push($this->suiteResults['suites'], $this->currentSuite);
242 }
243 }
244
245 246 247 248 249 250 251 252 253
254 private function getTestException(PHPUnit_Framework_Test $test, Exception $e) {
255
256 $testName = ereg_replace('(.*)\((.*[^)])\)', '\\2', $test->toString());
257 $trace = $e->getTrace();
258
259 for($i = 0; $i < count($trace); $i++) {
260
261 if(array_key_exists('file', $trace[$i])) {
262 if(stristr($trace[$i]['file'], $testName.'.php') != false) return $trace[$i];
263 }
264 if(array_key_exists('file:protected', $trace[$i])) {
265 if(stristr($trace[$i]['file:protected'], $testName.'.php') != false) return $trace[$i];
266 }
267 }
268 }
269
270 271 272
273 public function writeResults() {
274 $passCount = 0;
275 $failCount = 0;
276 $testCount = 0;
277 $errorCount = 0;
278
279 foreach($this->suiteResults['suites'] as $suite) {
280 foreach($suite['tests'] as $test) {
281 $testCount++;
282 ($test['status'] == 1) ? $passCount++ : $failCount++;
283 if ($test['status'] != 1) {
284 echo "<div class=\"failure\"><span>⊗ ". $this->testNameToPhrase($test['name']) ."</span><br>";
285 echo "<pre>".htmlentities($test['message'])."</pre><br>";
286 echo SS_Backtrace::get_rendered_backtrace($test['trace']);
287 echo "</div>";
288 }
289 }
290 }
291 $result = ($failCount > 0) ? 'fail' : 'pass';
292 echo "<div class=\"$result\">";
293 echo "<h2><span>$testCount</span> tests run: <span>$passCount</span> passes, <span>$failCount</span> fails, and <span>0</span> exceptions</h2>";
294 echo "</div>";
295
296 }
297
298 protected function testNameToPhrase($name) {
299 return ucfirst(preg_replace("/([a-z])([A-Z])/", "$1 $2", $name));
300 }
301
302 }
303
304 ?>
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the
Silverstripe Forums to ask development related questions.
-