Version 1
[yaffs-website] / vendor / phpunit / phpunit / src / TextUI / ResultPrinter.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 use SebastianBergmann\Environment\Console;
12
13 /**
14  * Prints the result of a TextUI TestRunner run.
15  *
16  * @since Class available since Release 2.0.0
17  */
18 class PHPUnit_TextUI_ResultPrinter extends PHPUnit_Util_Printer implements PHPUnit_Framework_TestListener
19 {
20     const EVENT_TEST_START      = 0;
21     const EVENT_TEST_END        = 1;
22     const EVENT_TESTSUITE_START = 2;
23     const EVENT_TESTSUITE_END   = 3;
24
25     const COLOR_NEVER   = 'never';
26     const COLOR_AUTO    = 'auto';
27     const COLOR_ALWAYS  = 'always';
28     const COLOR_DEFAULT = self::COLOR_NEVER;
29
30     /**
31      * @var array
32      */
33     private static $ansiCodes = array(
34       'bold'       => 1,
35       'fg-black'   => 30,
36       'fg-red'     => 31,
37       'fg-green'   => 32,
38       'fg-yellow'  => 33,
39       'fg-blue'    => 34,
40       'fg-magenta' => 35,
41       'fg-cyan'    => 36,
42       'fg-white'   => 37,
43       'bg-black'   => 40,
44       'bg-red'     => 41,
45       'bg-green'   => 42,
46       'bg-yellow'  => 43,
47       'bg-blue'    => 44,
48       'bg-magenta' => 45,
49       'bg-cyan'    => 46,
50       'bg-white'   => 47
51     );
52
53     /**
54      * @var int
55      */
56     protected $column = 0;
57
58     /**
59      * @var int
60      */
61     protected $maxColumn;
62
63     /**
64      * @var bool
65      */
66     protected $lastTestFailed = false;
67
68     /**
69      * @var int
70      */
71     protected $numAssertions = 0;
72
73     /**
74      * @var int
75      */
76     protected $numTests = -1;
77
78     /**
79      * @var int
80      */
81     protected $numTestsRun = 0;
82
83     /**
84      * @var int
85      */
86     protected $numTestsWidth;
87
88     /**
89      * @var bool
90      */
91     protected $colors = false;
92
93     /**
94      * @var bool
95      */
96     protected $debug = false;
97
98     /**
99      * @var bool
100      */
101     protected $verbose = false;
102
103     /**
104      * @var int
105      */
106     private $numberOfColumns;
107
108     /**
109      * Constructor.
110      *
111      * @param mixed      $out
112      * @param bool       $verbose
113      * @param string     $colors
114      * @param bool       $debug
115      * @param int|string $numberOfColumns
116      *
117      * @throws PHPUnit_Framework_Exception
118      *
119      * @since  Method available since Release 3.0.0
120      */
121     public function __construct($out = null, $verbose = false, $colors = self::COLOR_DEFAULT, $debug = false, $numberOfColumns = 80)
122     {
123         parent::__construct($out);
124
125         if (!is_bool($verbose)) {
126             throw PHPUnit_Util_InvalidArgumentHelper::factory(2, 'boolean');
127         }
128
129         $availableColors = array(self::COLOR_NEVER, self::COLOR_AUTO, self::COLOR_ALWAYS);
130
131         if (!in_array($colors, $availableColors)) {
132             throw PHPUnit_Util_InvalidArgumentHelper::factory(
133                 3,
134                 vsprintf('value from "%s", "%s" or "%s"', $availableColors)
135             );
136         }
137
138         if (!is_bool($debug)) {
139             throw PHPUnit_Util_InvalidArgumentHelper::factory(4, 'boolean');
140         }
141
142         if (!is_int($numberOfColumns) && $numberOfColumns != 'max') {
143             throw PHPUnit_Util_InvalidArgumentHelper::factory(5, 'integer or "max"');
144         }
145
146         $console            = new Console;
147         $maxNumberOfColumns = $console->getNumberOfColumns();
148
149         if ($numberOfColumns == 'max' || $numberOfColumns > $maxNumberOfColumns) {
150             $numberOfColumns = $maxNumberOfColumns;
151         }
152
153         $this->numberOfColumns = $numberOfColumns;
154         $this->verbose         = $verbose;
155         $this->debug           = $debug;
156
157         if ($colors === self::COLOR_AUTO && $console->hasColorSupport()) {
158             $this->colors = true;
159         } else {
160             $this->colors = (self::COLOR_ALWAYS === $colors);
161         }
162     }
163
164     /**
165      * @param PHPUnit_Framework_TestResult $result
166      */
167     public function printResult(PHPUnit_Framework_TestResult $result)
168     {
169         $this->printHeader();
170
171         $this->printErrors($result);
172         $printSeparator = $result->errorCount() > 0;
173
174         if ($printSeparator && $result->failureCount() > 0) {
175             $this->write("\n--\n\n");
176         }
177
178         $printSeparator = $printSeparator || $result->failureCount() > 0;
179         $this->printFailures($result);
180
181         if ($this->verbose) {
182             if ($printSeparator && $result->riskyCount() > 0) {
183                 $this->write("\n--\n\n");
184             }
185
186             $printSeparator = $printSeparator ||
187                               $result->riskyCount() > 0;
188
189             $this->printRisky($result);
190
191             if ($printSeparator && $result->notImplementedCount() > 0) {
192                 $this->write("\n--\n\n");
193             }
194
195             $printSeparator = $printSeparator ||
196                               $result->notImplementedCount() > 0;
197
198             $this->printIncompletes($result);
199
200             if ($printSeparator && $result->skippedCount() > 0) {
201                 $this->write("\n--\n\n");
202             }
203
204             $this->printSkipped($result);
205         }
206
207         $this->printFooter($result);
208     }
209
210     /**
211      * @param array  $defects
212      * @param string $type
213      */
214     protected function printDefects(array $defects, $type)
215     {
216         $count = count($defects);
217
218         if ($count == 0) {
219             return;
220         }
221
222         $this->write(
223             sprintf(
224                 "There %s %d %s%s:\n",
225                 ($count == 1) ? 'was' : 'were',
226                 $count,
227                 $type,
228                 ($count == 1) ? '' : 's'
229             )
230         );
231
232         $i = 1;
233
234         foreach ($defects as $defect) {
235             $this->printDefect($defect, $i++);
236         }
237     }
238
239     /**
240      * @param PHPUnit_Framework_TestFailure $defect
241      * @param int                           $count
242      */
243     protected function printDefect(PHPUnit_Framework_TestFailure $defect, $count)
244     {
245         $this->printDefectHeader($defect, $count);
246         $this->printDefectTrace($defect);
247     }
248
249     /**
250      * @param PHPUnit_Framework_TestFailure $defect
251      * @param int                           $count
252      */
253     protected function printDefectHeader(PHPUnit_Framework_TestFailure $defect, $count)
254     {
255         $this->write(
256             sprintf(
257                 "\n%d) %s\n",
258                 $count,
259                 $defect->getTestName()
260             )
261         );
262     }
263
264     /**
265      * @param PHPUnit_Framework_TestFailure $defect
266      */
267     protected function printDefectTrace(PHPUnit_Framework_TestFailure $defect)
268     {
269         $e = $defect->thrownException();
270         $this->write((string) $e);
271
272         while ($e = $e->getPrevious()) {
273             $this->write("\nCaused by\n" . $e);
274         }
275     }
276
277     /**
278      * @param PHPUnit_Framework_TestResult $result
279      */
280     protected function printErrors(PHPUnit_Framework_TestResult $result)
281     {
282         $this->printDefects($result->errors(), 'error');
283     }
284
285     /**
286      * @param PHPUnit_Framework_TestResult $result
287      */
288     protected function printFailures(PHPUnit_Framework_TestResult $result)
289     {
290         $this->printDefects($result->failures(), 'failure');
291     }
292
293     /**
294      * @param PHPUnit_Framework_TestResult $result
295      */
296     protected function printIncompletes(PHPUnit_Framework_TestResult $result)
297     {
298         $this->printDefects($result->notImplemented(), 'incomplete test');
299     }
300
301     /**
302      * @param PHPUnit_Framework_TestResult $result
303      *
304      * @since  Method available since Release 4.0.0
305      */
306     protected function printRisky(PHPUnit_Framework_TestResult $result)
307     {
308         $this->printDefects($result->risky(), 'risky test');
309     }
310
311     /**
312      * @param PHPUnit_Framework_TestResult $result
313      *
314      * @since  Method available since Release 3.0.0
315      */
316     protected function printSkipped(PHPUnit_Framework_TestResult $result)
317     {
318         $this->printDefects($result->skipped(), 'skipped test');
319     }
320
321     protected function printHeader()
322     {
323         $this->write("\n\n" . PHP_Timer::resourceUsage() . "\n\n");
324     }
325
326     /**
327      * @param PHPUnit_Framework_TestResult $result
328      */
329     protected function printFooter(PHPUnit_Framework_TestResult $result)
330     {
331         if (count($result) === 0) {
332             $this->writeWithColor(
333                 'fg-black, bg-yellow',
334                 'No tests executed!'
335             );
336         } elseif ($result->wasSuccessful() &&
337                  $result->allHarmless() &&
338                  $result->allCompletelyImplemented() &&
339                  $result->noneSkipped()) {
340             $this->writeWithColor(
341                 'fg-black, bg-green',
342                 sprintf(
343                     'OK (%d test%s, %d assertion%s)',
344                     count($result),
345                     (count($result) == 1) ? '' : 's',
346                     $this->numAssertions,
347                     ($this->numAssertions == 1) ? '' : 's'
348                 )
349             );
350         } else {
351             if ($result->wasSuccessful()) {
352                 $color = 'fg-black, bg-yellow';
353
354                 if ($this->verbose) {
355                     $this->write("\n");
356                 }
357
358                 $this->writeWithColor(
359                     $color,
360                     'OK, but incomplete, skipped, or risky tests!'
361                 );
362             } else {
363                 $color = 'fg-white, bg-red';
364
365                 $this->write("\n");
366                 $this->writeWithColor($color, 'FAILURES!');
367             }
368
369             $this->writeCountString(count($result), 'Tests', $color, true);
370             $this->writeCountString($this->numAssertions, 'Assertions', $color, true);
371             $this->writeCountString($result->errorCount(), 'Errors', $color);
372             $this->writeCountString($result->failureCount(), 'Failures', $color);
373             $this->writeCountString($result->skippedCount(), 'Skipped', $color);
374             $this->writeCountString($result->notImplementedCount(), 'Incomplete', $color);
375             $this->writeCountString($result->riskyCount(), 'Risky', $color);
376             $this->writeWithColor($color, '.', true);
377         }
378     }
379
380     /**
381      */
382     public function printWaitPrompt()
383     {
384         $this->write("\n<RETURN> to continue\n");
385     }
386
387     /**
388      * An error occurred.
389      *
390      * @param PHPUnit_Framework_Test $test
391      * @param Exception              $e
392      * @param float                  $time
393      */
394     public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
395     {
396         $this->writeProgressWithColor('fg-red, bold', 'E');
397         $this->lastTestFailed = true;
398     }
399
400     /**
401      * A failure occurred.
402      *
403      * @param PHPUnit_Framework_Test                 $test
404      * @param PHPUnit_Framework_AssertionFailedError $e
405      * @param float                                  $time
406      */
407     public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
408     {
409         $this->writeProgressWithColor('bg-red, fg-white', 'F');
410         $this->lastTestFailed = true;
411     }
412
413     /**
414      * Incomplete test.
415      *
416      * @param PHPUnit_Framework_Test $test
417      * @param Exception              $e
418      * @param float                  $time
419      */
420     public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time)
421     {
422         $this->writeProgressWithColor('fg-yellow, bold', 'I');
423         $this->lastTestFailed = true;
424     }
425
426     /**
427      * Risky test.
428      *
429      * @param PHPUnit_Framework_Test $test
430      * @param Exception              $e
431      * @param float                  $time
432      *
433      * @since  Method available since Release 4.0.0
434      */
435     public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time)
436     {
437         $this->writeProgressWithColor('fg-yellow, bold', 'R');
438         $this->lastTestFailed = true;
439     }
440
441     /**
442      * Skipped test.
443      *
444      * @param PHPUnit_Framework_Test $test
445      * @param Exception              $e
446      * @param float                  $time
447      *
448      * @since  Method available since Release 3.0.0
449      */
450     public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time)
451     {
452         $this->writeProgressWithColor('fg-cyan, bold', 'S');
453         $this->lastTestFailed = true;
454     }
455
456     /**
457      * A testsuite started.
458      *
459      * @param PHPUnit_Framework_TestSuite $suite
460      *
461      * @since  Method available since Release 2.2.0
462      */
463     public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
464     {
465         if ($this->numTests == -1) {
466             $this->numTests      = count($suite);
467             $this->numTestsWidth = strlen((string) $this->numTests);
468             $this->maxColumn     = $this->numberOfColumns - strlen('  /  (XXX%)') - (2 * $this->numTestsWidth);
469         }
470     }
471
472     /**
473      * A testsuite ended.
474      *
475      * @param PHPUnit_Framework_TestSuite $suite
476      *
477      * @since  Method available since Release 2.2.0
478      */
479     public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
480     {
481     }
482
483     /**
484      * A test started.
485      *
486      * @param PHPUnit_Framework_Test $test
487      */
488     public function startTest(PHPUnit_Framework_Test $test)
489     {
490         if ($this->debug) {
491             $this->write(
492                 sprintf(
493                     "\nStarting test '%s'.\n",
494                     PHPUnit_Util_Test::describe($test)
495                 )
496             );
497         }
498     }
499
500     /**
501      * A test ended.
502      *
503      * @param PHPUnit_Framework_Test $test
504      * @param float                  $time
505      */
506     public function endTest(PHPUnit_Framework_Test $test, $time)
507     {
508         if (!$this->lastTestFailed) {
509             $this->writeProgress('.');
510         }
511
512         if ($test instanceof PHPUnit_Framework_TestCase) {
513             $this->numAssertions += $test->getNumAssertions();
514         } elseif ($test instanceof PHPUnit_Extensions_PhptTestCase) {
515             $this->numAssertions++;
516         }
517
518         $this->lastTestFailed = false;
519
520         if ($test instanceof PHPUnit_Framework_TestCase) {
521             if (!$test->hasExpectationOnOutput()) {
522                 $this->write($test->getActualOutput());
523             }
524         }
525     }
526
527     /**
528      * @param string $progress
529      */
530     protected function writeProgress($progress)
531     {
532         $this->write($progress);
533         $this->column++;
534         $this->numTestsRun++;
535
536         if ($this->column == $this->maxColumn) {
537             $this->write(
538                 sprintf(
539                     ' %' . $this->numTestsWidth . 'd / %' .
540                     $this->numTestsWidth . 'd (%3s%%)',
541                     $this->numTestsRun,
542                     $this->numTests,
543                     floor(($this->numTestsRun / $this->numTests) * 100)
544                 )
545             );
546
547             $this->writeNewLine();
548         }
549     }
550
551     protected function writeNewLine()
552     {
553         $this->column = 0;
554         $this->write("\n");
555     }
556
557     /**
558      * Formats a buffer with a specified ANSI color sequence if colors are
559      * enabled.
560      *
561      * @param string $color
562      * @param string $buffer
563      *
564      * @return string
565      *
566      * @since  Method available since Release 4.0.0
567      */
568     protected function formatWithColor($color, $buffer)
569     {
570         if (!$this->colors) {
571             return $buffer;
572         }
573
574         $codes   = array_map('trim', explode(',', $color));
575         $lines   = explode("\n", $buffer);
576         $padding = max(array_map('strlen', $lines));
577         $styles  = array();
578
579         foreach ($codes as $code) {
580             $styles[] = self::$ansiCodes[$code];
581         }
582
583         $style = sprintf("\x1b[%sm", implode(';', $styles));
584
585         $styledLines = array();
586
587         foreach ($lines as $line) {
588             $styledLines[] = $style . str_pad($line, $padding) . "\x1b[0m";
589         }
590
591         return implode("\n", $styledLines);
592     }
593
594     /**
595      * Writes a buffer out with a color sequence if colors are enabled.
596      *
597      * @param string $color
598      * @param string $buffer
599      * @param bool   $lf
600      *
601      * @since  Method available since Release 4.0.0
602      */
603     protected function writeWithColor($color, $buffer, $lf = true)
604     {
605         $this->write($this->formatWithColor($color, $buffer));
606
607         if ($lf) {
608             $this->write("\n");
609         }
610     }
611
612     /**
613      * Writes progress with a color sequence if colors are enabled.
614      *
615      * @param string $color
616      * @param string $buffer
617      *
618      * @since  Method available since Release 4.0.0
619      */
620     protected function writeProgressWithColor($color, $buffer)
621     {
622         $buffer = $this->formatWithColor($color, $buffer);
623         $this->writeProgress($buffer);
624     }
625
626     /**
627      * @param int    $count
628      * @param string $name
629      * @param string $color
630      * @param bool   $always
631      *
632      * @since  Method available since Release 4.6.5
633      */
634     private function writeCountString($count, $name, $color, $always = false)
635     {
636         static $first = true;
637
638         if ($always || $count > 0) {
639             $this->writeWithColor(
640                 $color,
641                 sprintf(
642                     '%s%s: %d',
643                     !$first ? ', ' : '',
644                     $name,
645                     $count
646                 ),
647                 false
648             );
649
650             $first = false;
651         }
652     }
653 }