6b68405b93d9161a40a0c8a6d4ad911c8e82a1f2
[yaffs-website] / vendor / phpunit / phpunit / src / Util / Log / JUnit.php
1 <?php
2 /*
3  * This file is part of PHPUnit.
4  *
5  * (c) Sebastian Bergmann <sebastian@phpunit.de>
6  *
7  * For the full copyright and license information, please view the LICENSE
8  * file that was distributed with this source code.
9  */
10
11 /**
12  * A TestListener that generates a logfile of the test execution in XML markup.
13  *
14  * The XML markup used is the same as the one that is used by the JUnit Ant task.
15  *
16  * @since Class available since Release 2.1.0
17  */
18 class PHPUnit_Util_Log_JUnit extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener
19 {
20     /**
21      * @var DOMDocument
22      */
23     protected $document;
24
25     /**
26      * @var DOMElement
27      */
28     protected $root;
29
30     /**
31      * @var bool
32      */
33     protected $logIncompleteSkipped = false;
34
35     /**
36      * @var bool
37      */
38     protected $writeDocument = true;
39
40     /**
41      * @var DOMElement[]
42      */
43     protected $testSuites = array();
44
45     /**
46      * @var int[]
47      */
48     protected $testSuiteTests = array(0);
49
50     /**
51      * @var int[]
52      */
53     protected $testSuiteAssertions = array(0);
54
55     /**
56      * @var int[]
57      */
58     protected $testSuiteErrors = array(0);
59
60     /**
61      * @var int[]
62      */
63     protected $testSuiteFailures = array(0);
64
65     /**
66      * @var int[]
67      */
68     protected $testSuiteTimes = array(0);
69
70     /**
71      * @var int
72      */
73     protected $testSuiteLevel = 0;
74
75     /**
76      * @var DOMElement
77      */
78     protected $currentTestCase = null;
79
80     /**
81      * @var bool
82      */
83     protected $attachCurrentTestCase = true;
84
85     /**
86      * Constructor.
87      *
88      * @param mixed $out
89      * @param bool  $logIncompleteSkipped
90      */
91     public function __construct($out = null, $logIncompleteSkipped = false)
92     {
93         $this->document               = new DOMDocument('1.0', 'UTF-8');
94         $this->document->formatOutput = true;
95
96         $this->root = $this->document->createElement('testsuites');
97         $this->document->appendChild($this->root);
98
99         parent::__construct($out);
100
101         $this->logIncompleteSkipped = $logIncompleteSkipped;
102     }
103
104     /**
105      * Flush buffer and close output.
106      */
107     public function flush()
108     {
109         if ($this->writeDocument === true) {
110             $this->write($this->getXML());
111         }
112
113         parent::flush();
114     }
115
116     /**
117      * An error occurred.
118      *
119      * @param PHPUnit_Framework_Test $test
120      * @param Exception              $e
121      * @param float                  $time
122      */
123     public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
124     {
125         if ($this->currentTestCase === null) {
126             return;
127         }
128
129         if ($test instanceof PHPUnit_Framework_SelfDescribing) {
130             $buffer = $test->toString() . PHP_EOL;
131         } else {
132             $buffer = '';
133         }
134
135         if ($e instanceof PHPUnit_Framework_ExceptionWrapper) {
136             $type    = $e->getClassname();
137             $buffer .= (string) $e;
138         } else {
139             $type    = get_class($e);
140             $buffer .= PHPUnit_Framework_TestFailure::exceptionToString($e) . PHP_EOL .
141                        PHPUnit_Util_Filter::getFilteredStacktrace($e);
142         }
143
144         $error = $this->document->createElement(
145             'error',
146             PHPUnit_Util_XML::prepareString($buffer)
147         );
148
149         $error->setAttribute('type', $type);
150
151         $this->currentTestCase->appendChild($error);
152
153         $this->testSuiteErrors[$this->testSuiteLevel]++;
154     }
155
156     /**
157      * A failure occurred.
158      *
159      * @param PHPUnit_Framework_Test                 $test
160      * @param PHPUnit_Framework_AssertionFailedError $e
161      * @param float                                  $time
162      */
163     public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
164     {
165         if ($this->currentTestCase === null) {
166             return;
167         }
168
169         if ($test instanceof PHPUnit_Framework_SelfDescribing) {
170             $buffer = $test->toString() . "\n";
171         } else {
172             $buffer = '';
173         }
174
175         $buffer .= PHPUnit_Framework_TestFailure::exceptionToString($e) .
176                    "\n" .
177                    PHPUnit_Util_Filter::getFilteredStacktrace($e);
178
179         $failure = $this->document->createElement(
180             'failure',
181             PHPUnit_Util_XML::prepareString($buffer)
182         );
183
184         $failure->setAttribute('type', get_class($e));
185
186         $this->currentTestCase->appendChild($failure);
187
188         $this->testSuiteFailures[$this->testSuiteLevel]++;
189     }
190
191     /**
192      * Incomplete test.
193      *
194      * @param PHPUnit_Framework_Test $test
195      * @param Exception              $e
196      * @param float                  $time
197      */
198     public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time)
199     {
200         if ($this->logIncompleteSkipped && $this->currentTestCase !== null) {
201             $error = $this->document->createElement(
202                 'error',
203                 PHPUnit_Util_XML::prepareString(
204                     "Incomplete Test\n" .
205                     PHPUnit_Util_Filter::getFilteredStacktrace($e)
206                 )
207             );
208
209             $error->setAttribute('type', get_class($e));
210
211             $this->currentTestCase->appendChild($error);
212
213             $this->testSuiteErrors[$this->testSuiteLevel]++;
214         } else {
215             $this->attachCurrentTestCase = false;
216         }
217     }
218
219     /**
220      * Risky test.
221      *
222      * @param PHPUnit_Framework_Test $test
223      * @param Exception              $e
224      * @param float                  $time
225      *
226      * @since  Method available since Release 4.0.0
227      */
228     public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time)
229     {
230         if ($this->logIncompleteSkipped && $this->currentTestCase !== null) {
231             $error = $this->document->createElement(
232                 'error',
233                 PHPUnit_Util_XML::prepareString(
234                     "Risky Test\n" .
235                     PHPUnit_Util_Filter::getFilteredStacktrace($e)
236                 )
237             );
238
239             $error->setAttribute('type', get_class($e));
240
241             $this->currentTestCase->appendChild($error);
242
243             $this->testSuiteErrors[$this->testSuiteLevel]++;
244         } else {
245             $this->attachCurrentTestCase = false;
246         }
247     }
248
249     /**
250      * Skipped test.
251      *
252      * @param PHPUnit_Framework_Test $test
253      * @param Exception              $e
254      * @param float                  $time
255      *
256      * @since  Method available since Release 3.0.0
257      */
258     public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time)
259     {
260         if ($this->logIncompleteSkipped && $this->currentTestCase !== null) {
261             $error = $this->document->createElement(
262                 'error',
263                 PHPUnit_Util_XML::prepareString(
264                     "Skipped Test\n" .
265                     PHPUnit_Util_Filter::getFilteredStacktrace($e)
266                 )
267             );
268
269             $error->setAttribute('type', get_class($e));
270
271             $this->currentTestCase->appendChild($error);
272
273             $this->testSuiteErrors[$this->testSuiteLevel]++;
274         } else {
275             $this->attachCurrentTestCase = false;
276         }
277     }
278
279     /**
280      * A testsuite started.
281      *
282      * @param PHPUnit_Framework_TestSuite $suite
283      *
284      * @since  Method available since Release 2.2.0
285      */
286     public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
287     {
288         $testSuite = $this->document->createElement('testsuite');
289         $testSuite->setAttribute('name', $suite->getName());
290
291         if (class_exists($suite->getName(), false)) {
292             try {
293                 $class = new ReflectionClass($suite->getName());
294
295                 $testSuite->setAttribute('file', $class->getFileName());
296             } catch (ReflectionException $e) {
297             }
298         }
299
300         if ($this->testSuiteLevel > 0) {
301             $this->testSuites[$this->testSuiteLevel]->appendChild($testSuite);
302         } else {
303             $this->root->appendChild($testSuite);
304         }
305
306         $this->testSuiteLevel++;
307         $this->testSuites[$this->testSuiteLevel]          = $testSuite;
308         $this->testSuiteTests[$this->testSuiteLevel]      = 0;
309         $this->testSuiteAssertions[$this->testSuiteLevel] = 0;
310         $this->testSuiteErrors[$this->testSuiteLevel]     = 0;
311         $this->testSuiteFailures[$this->testSuiteLevel]   = 0;
312         $this->testSuiteTimes[$this->testSuiteLevel]      = 0;
313     }
314
315     /**
316      * A testsuite ended.
317      *
318      * @param PHPUnit_Framework_TestSuite $suite
319      *
320      * @since  Method available since Release 2.2.0
321      */
322     public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
323     {
324         $this->testSuites[$this->testSuiteLevel]->setAttribute(
325             'tests',
326             $this->testSuiteTests[$this->testSuiteLevel]
327         );
328
329         $this->testSuites[$this->testSuiteLevel]->setAttribute(
330             'assertions',
331             $this->testSuiteAssertions[$this->testSuiteLevel]
332         );
333
334         $this->testSuites[$this->testSuiteLevel]->setAttribute(
335             'failures',
336             $this->testSuiteFailures[$this->testSuiteLevel]
337         );
338
339         $this->testSuites[$this->testSuiteLevel]->setAttribute(
340             'errors',
341             $this->testSuiteErrors[$this->testSuiteLevel]
342         );
343
344         $this->testSuites[$this->testSuiteLevel]->setAttribute(
345             'time',
346             sprintf('%F', $this->testSuiteTimes[$this->testSuiteLevel])
347         );
348
349         if ($this->testSuiteLevel > 1) {
350             $this->testSuiteTests[$this->testSuiteLevel - 1]      += $this->testSuiteTests[$this->testSuiteLevel];
351             $this->testSuiteAssertions[$this->testSuiteLevel - 1] += $this->testSuiteAssertions[$this->testSuiteLevel];
352             $this->testSuiteErrors[$this->testSuiteLevel - 1]     += $this->testSuiteErrors[$this->testSuiteLevel];
353             $this->testSuiteFailures[$this->testSuiteLevel - 1]   += $this->testSuiteFailures[$this->testSuiteLevel];
354             $this->testSuiteTimes[$this->testSuiteLevel - 1]      += $this->testSuiteTimes[$this->testSuiteLevel];
355         }
356
357         $this->testSuiteLevel--;
358     }
359
360     /**
361      * A test started.
362      *
363      * @param PHPUnit_Framework_Test $test
364      */
365     public function startTest(PHPUnit_Framework_Test $test)
366     {
367         $testCase = $this->document->createElement('testcase');
368         $testCase->setAttribute('name', $test->getName());
369
370         if ($test instanceof PHPUnit_Framework_TestCase) {
371             $class      = new ReflectionClass($test);
372             $methodName = $test->getName();
373
374             if ($class->hasMethod($methodName)) {
375                 $method = $class->getMethod($test->getName());
376
377                 $testCase->setAttribute('class', $class->getName());
378                 $testCase->setAttribute('file', $class->getFileName());
379                 $testCase->setAttribute('line', $method->getStartLine());
380             }
381         }
382
383         $this->currentTestCase = $testCase;
384     }
385
386     /**
387      * A test ended.
388      *
389      * @param PHPUnit_Framework_Test $test
390      * @param float                  $time
391      */
392     public function endTest(PHPUnit_Framework_Test $test, $time)
393     {
394         if ($this->attachCurrentTestCase) {
395             if ($test instanceof PHPUnit_Framework_TestCase) {
396                 $numAssertions = $test->getNumAssertions();
397                 $this->testSuiteAssertions[$this->testSuiteLevel] += $numAssertions;
398
399                 $this->currentTestCase->setAttribute(
400                     'assertions',
401                     $numAssertions
402                 );
403             }
404
405             $this->currentTestCase->setAttribute(
406                 'time',
407                 sprintf('%F', $time)
408             );
409
410             $this->testSuites[$this->testSuiteLevel]->appendChild(
411                 $this->currentTestCase
412             );
413
414             $this->testSuiteTests[$this->testSuiteLevel]++;
415             $this->testSuiteTimes[$this->testSuiteLevel] += $time;
416
417             if (method_exists($test, 'hasOutput') && $test->hasOutput()) {
418                 $systemOut = $this->document->createElement('system-out');
419                 $systemOut->appendChild(
420                     $this->document->createTextNode($test->getActualOutput())
421                 );
422                 $this->currentTestCase->appendChild($systemOut);
423             }
424         }
425
426         $this->attachCurrentTestCase = true;
427         $this->currentTestCase       = null;
428     }
429
430     /**
431      * Returns the XML as a string.
432      *
433      * @return string
434      *
435      * @since  Method available since Release 2.2.0
436      */
437     public function getXML()
438     {
439         return $this->document->saveXML();
440     }
441
442     /**
443      * Enables or disables the writing of the document
444      * in flush().
445      *
446      * This is a "hack" needed for the integration of
447      * PHPUnit with Phing.
448      *
449      * @return string
450      *
451      * @since  Method available since Release 2.2.0
452      */
453     public function setWriteDocument($flag)
454     {
455         if (is_bool($flag)) {
456             $this->writeDocument = $flag;
457         }
458     }
459 }