Completed
Branch development (b1b115)
by Johannes
10:28
created

PHPUnit_Framework_TestResult   F

Complexity

Total Complexity 181

Size/Duplication

Total Lines 1288
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 181
c 0
b 0
f 0
dl 0
loc 1288
rs 0.8

How to fix   Complexity   

Complex Class

Complex classes like PHPUnit_Framework_TestResult often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PHPUnit_Framework_TestResult, and based on these observations, apply Extract Interface, too.

1
<?php
2
/*
3
 * This file is part of PHPUnit.
4
 *
5
 * (c) Sebastian Bergmann <[email protected]>
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\CodeCoverage\CodeCoverage;
12
use SebastianBergmann\CodeCoverage\Exception as CodeCoverageException;
13
use SebastianBergmann\CodeCoverage\CoveredCodeNotExecutedException;
14
use SebastianBergmann\CodeCoverage\MissingCoversAnnotationException;
15
use SebastianBergmann\CodeCoverage\UnintentionallyCoveredCodeException;
16
use SebastianBergmann\ResourceOperations\ResourceOperations;
17
18
/**
19
 * A TestResult collects the results of executing a test case.
20
 */
21
class PHPUnit_Framework_TestResult implements Countable
22
{
23
    /**
24
     * @var array
25
     */
26
    protected $passed = [];
27
28
    /**
29
     * @var array
30
     */
31
    protected $errors = [];
32
33
    /**
34
     * @var array
35
     */
36
    protected $failures = [];
37
38
    /**
39
     * @var array
40
     */
41
    protected $warnings = [];
42
43
    /**
44
     * @var array
45
     */
46
    protected $notImplemented = [];
47
48
    /**
49
     * @var array
50
     */
51
    protected $risky = [];
52
53
    /**
54
     * @var array
55
     */
56
    protected $skipped = [];
57
58
    /**
59
     * @var array
60
     */
61
    protected $listeners = [];
62
63
    /**
64
     * @var int
65
     */
66
    protected $runTests = 0;
67
68
    /**
69
     * @var float
70
     */
71
    protected $time = 0;
72
73
    /**
74
     * @var PHPUnit_Framework_TestSuite
75
     */
76
    protected $topTestSuite = null;
77
78
    /**
79
     * Code Coverage information.
80
     *
81
     * @var CodeCoverage
82
     */
83
    protected $codeCoverage;
84
85
    /**
86
     * @var bool
87
     */
88
    protected $convertErrorsToExceptions = true;
89
90
    /**
91
     * @var bool
92
     */
93
    protected $stop = false;
94
95
    /**
96
     * @var bool
97
     */
98
    protected $stopOnError = false;
99
100
    /**
101
     * @var bool
102
     */
103
    protected $stopOnFailure = false;
104
105
    /**
106
     * @var bool
107
     */
108
    protected $stopOnWarning = false;
109
110
    /**
111
     * @var bool
112
     */
113
    protected $beStrictAboutTestsThatDoNotTestAnything = false;
114
115
    /**
116
     * @var bool
117
     */
118
    protected $beStrictAboutOutputDuringTests = false;
119
120
    /**
121
     * @var bool
122
     */
123
    protected $beStrictAboutTodoAnnotatedTests = false;
124
125
    /**
126
     * @var bool
127
     */
128
    protected $beStrictAboutResourceUsageDuringSmallTests = false;
129
130
    /**
131
     * @var bool
132
     */
133
    protected $enforceTimeLimit = false;
134
135
    /**
136
     * @var int
137
     */
138
    protected $timeoutForSmallTests = 1;
139
140
    /**
141
     * @var int
142
     */
143
    protected $timeoutForMediumTests = 10;
144
145
    /**
146
     * @var int
147
     */
148
    protected $timeoutForLargeTests = 60;
149
150
    /**
151
     * @var bool
152
     */
153
    protected $stopOnRisky = false;
154
155
    /**
156
     * @var bool
157
     */
158
    protected $stopOnIncomplete = false;
159
160
    /**
161
     * @var bool
162
     */
163
    protected $stopOnSkipped = false;
164
165
    /**
166
     * @var bool
167
     */
168
    protected $lastTestFailed = false;
169
170
    /**
171
     * @var bool
172
     */
173
    private $registerMockObjectsFromTestArgumentsRecursively = false;
174
175
    /**
176
     * Registers a TestListener.
177
     *
178
     * @param  PHPUnit_Framework_TestListener
179
     */
180
    public function addListener(PHPUnit_Framework_TestListener $listener)
181
    {
182
        $this->listeners[] = $listener;
183
    }
184
185
    /**
186
     * Unregisters a TestListener.
187
     *
188
     * @param PHPUnit_Framework_TestListener $listener
189
     */
190
    public function removeListener(PHPUnit_Framework_TestListener $listener)
191
    {
192
        foreach ($this->listeners as $key => $_listener) {
193
            if ($listener === $_listener) {
194
                unset($this->listeners[$key]);
195
            }
196
        }
197
    }
198
199
    /**
200
     * Flushes all flushable TestListeners.
201
     */
202
    public function flushListeners()
203
    {
204
        foreach ($this->listeners as $listener) {
205
            if ($listener instanceof PHPUnit_Util_Printer) {
206
                $listener->flush();
207
            }
208
        }
209
    }
210
211
    /**
212
     * Adds an error to the list of errors.
213
     *
214
     * @param PHPUnit_Framework_Test $test
215
     * @param Throwable              $t
216
     * @param float                  $time
217
     */
218
    public function addError(PHPUnit_Framework_Test $test, $t, $time)
219
    {
220
        if ($t instanceof PHPUnit_Framework_RiskyTest) {
221
            $this->risky[] = new PHPUnit_Framework_TestFailure($test, $t);
222
            $notifyMethod  = 'addRiskyTest';
223
224
            if ($test instanceof PHPUnit_Framework_TestCase) {
225
                $test->markAsRisky();
226
            }
227
228
            if ($this->stopOnRisky) {
229
                $this->stop();
230
            }
231
        } elseif ($t instanceof PHPUnit_Framework_IncompleteTest) {
232
            $this->notImplemented[] = new PHPUnit_Framework_TestFailure($test, $t);
233
            $notifyMethod           = 'addIncompleteTest';
234
235
            if ($this->stopOnIncomplete) {
236
                $this->stop();
237
            }
238
        } elseif ($t instanceof PHPUnit_Framework_SkippedTest) {
239
            $this->skipped[] = new PHPUnit_Framework_TestFailure($test, $t);
240
            $notifyMethod    = 'addSkippedTest';
241
242
            if ($this->stopOnSkipped) {
243
                $this->stop();
244
            }
245
        } else {
246
            $this->errors[] = new PHPUnit_Framework_TestFailure($test, $t);
247
            $notifyMethod   = 'addError';
248
249
            if ($this->stopOnError || $this->stopOnFailure) {
250
                $this->stop();
251
            }
252
        }
253
254
        // @see https://github.com/sebastianbergmann/phpunit/issues/1953
255
        if ($t instanceof Error) {
256
            $t = new PHPUnit_Framework_ExceptionWrapper($t);
257
        }
258
259
        foreach ($this->listeners as $listener) {
260
            $listener->$notifyMethod($test, $t, $time);
261
        }
262
263
        $this->lastTestFailed = true;
264
        $this->time          += $time;
265
    }
266
267
    /**
268
     * Adds a warning to the list of warnings.
269
     * The passed in exception caused the warning.
270
     *
271
     * @param PHPUnit_Framework_Test    $test
272
     * @param PHPUnit_Framework_Warning $e
273
     * @param float                     $time
274
     */
275
    public function addWarning(PHPUnit_Framework_Test $test, PHPUnit_Framework_Warning $e, $time)
276
    {
277
        if ($this->stopOnWarning) {
278
            $this->stop();
279
        }
280
281
        $this->warnings[] = new PHPUnit_Framework_TestFailure($test, $e);
282
283
        foreach ($this->listeners as $listener) {
284
            // @todo Remove check for PHPUnit 6.0.0
285
            // @see  https://github.com/sebastianbergmann/phpunit/pull/1840#issuecomment-162535997
286
            if (method_exists($listener, 'addWarning')) {
287
                $listener->addWarning($test, $e, $time);
288
            }
289
        }
290
291
        $this->time += $time;
292
    }
293
294
    /**
295
     * Adds a failure to the list of failures.
296
     * The passed in exception caused the failure.
297
     *
298
     * @param PHPUnit_Framework_Test                 $test
299
     * @param PHPUnit_Framework_AssertionFailedError $e
300
     * @param float                                  $time
301
     */
302
    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
303
    {
304
        if ($e instanceof PHPUnit_Framework_RiskyTest ||
305
            $e instanceof PHPUnit_Framework_OutputError) {
306
            $this->risky[] = new PHPUnit_Framework_TestFailure($test, $e);
307
            $notifyMethod  = 'addRiskyTest';
308
309
            if ($test instanceof PHPUnit_Framework_TestCase) {
310
                $test->markAsRisky();
311
            }
312
313
            if ($this->stopOnRisky) {
314
                $this->stop();
315
            }
316
        } elseif ($e instanceof PHPUnit_Framework_IncompleteTest) {
317
            $this->notImplemented[] = new PHPUnit_Framework_TestFailure($test, $e);
318
            $notifyMethod           = 'addIncompleteTest';
319
320
            if ($this->stopOnIncomplete) {
321
                $this->stop();
322
            }
323
        } elseif ($e instanceof PHPUnit_Framework_SkippedTest) {
324
            $this->skipped[] = new PHPUnit_Framework_TestFailure($test, $e);
325
            $notifyMethod    = 'addSkippedTest';
326
327
            if ($this->stopOnSkipped) {
328
                $this->stop();
329
            }
330
        } else {
331
            $this->failures[] = new PHPUnit_Framework_TestFailure($test, $e);
332
            $notifyMethod     = 'addFailure';
333
334
            if ($this->stopOnFailure) {
335
                $this->stop();
336
            }
337
        }
338
339
        foreach ($this->listeners as $listener) {
340
            $listener->$notifyMethod($test, $e, $time);
341
        }
342
343
        $this->lastTestFailed = true;
344
        $this->time          += $time;
345
    }
346
347
    /**
348
     * Informs the result that a testsuite will be started.
349
     *
350
     * @param PHPUnit_Framework_TestSuite $suite
351
     */
352
    public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
353
    {
354
        if ($this->topTestSuite === null) {
355
            $this->topTestSuite = $suite;
356
        }
357
358
        foreach ($this->listeners as $listener) {
359
            $listener->startTestSuite($suite);
360
        }
361
    }
362
363
    /**
364
     * Informs the result that a testsuite was completed.
365
     *
366
     * @param PHPUnit_Framework_TestSuite $suite
367
     */
368
    public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
369
    {
370
        foreach ($this->listeners as $listener) {
371
            $listener->endTestSuite($suite);
372
        }
373
    }
374
375
    /**
376
     * Informs the result that a test will be started.
377
     *
378
     * @param PHPUnit_Framework_Test $test
379
     */
380
    public function startTest(PHPUnit_Framework_Test $test)
381
    {
382
        $this->lastTestFailed = false;
383
        $this->runTests      += count($test);
384
385
        foreach ($this->listeners as $listener) {
386
            $listener->startTest($test);
387
        }
388
    }
389
390
    /**
391
     * Informs the result that a test was completed.
392
     *
393
     * @param PHPUnit_Framework_Test $test
394
     * @param float                  $time
395
     */
396
    public function endTest(PHPUnit_Framework_Test $test, $time)
397
    {
398
        foreach ($this->listeners as $listener) {
399
            $listener->endTest($test, $time);
400
        }
401
402
        if (!$this->lastTestFailed && $test instanceof PHPUnit_Framework_TestCase) {
403
            $class  = get_class($test);
404
            $key    = $class . '::' . $test->getName();
405
406
            $this->passed[$key] = [
407
                'result' => $test->getResult(),
408
                'size'   => PHPUnit_Util_Test::getSize(
409
                    $class,
410
                    $test->getName(false)
411
                )
412
            ];
413
414
            $this->time += $time;
415
        }
416
    }
417
418
    /**
419
     * Returns true if no risky test occurred.
420
     *
421
     * @return bool
422
     */
423
    public function allHarmless()
424
    {
425
        return $this->riskyCount() == 0;
426
    }
427
428
    /**
429
     * Gets the number of risky tests.
430
     *
431
     * @return int
432
     */
433
    public function riskyCount()
434
    {
435
        return count($this->risky);
436
    }
437
438
    /**
439
     * Returns true if no incomplete test occurred.
440
     *
441
     * @return bool
442
     */
443
    public function allCompletelyImplemented()
444
    {
445
        return $this->notImplementedCount() == 0;
446
    }
447
448
    /**
449
     * Gets the number of incomplete tests.
450
     *
451
     * @return int
452
     */
453
    public function notImplementedCount()
454
    {
455
        return count($this->notImplemented);
456
    }
457
458
    /**
459
     * Returns an Enumeration for the risky tests.
460
     *
461
     * @return array
462
     */
463
    public function risky()
464
    {
465
        return $this->risky;
466
    }
467
468
    /**
469
     * Returns an Enumeration for the incomplete tests.
470
     *
471
     * @return array
472
     */
473
    public function notImplemented()
474
    {
475
        return $this->notImplemented;
476
    }
477
478
    /**
479
     * Returns true if no test has been skipped.
480
     *
481
     * @return bool
482
     */
483
    public function noneSkipped()
484
    {
485
        return $this->skippedCount() == 0;
486
    }
487
488
    /**
489
     * Gets the number of skipped tests.
490
     *
491
     * @return int
492
     */
493
    public function skippedCount()
494
    {
495
        return count($this->skipped);
496
    }
497
498
    /**
499
     * Returns an Enumeration for the skipped tests.
500
     *
501
     * @return array
502
     */
503
    public function skipped()
504
    {
505
        return $this->skipped;
506
    }
507
508
    /**
509
     * Gets the number of detected errors.
510
     *
511
     * @return int
512
     */
513
    public function errorCount()
514
    {
515
        return count($this->errors);
516
    }
517
518
    /**
519
     * Returns an Enumeration for the errors.
520
     *
521
     * @return array
522
     */
523
    public function errors()
524
    {
525
        return $this->errors;
526
    }
527
528
    /**
529
     * Gets the number of detected failures.
530
     *
531
     * @return int
532
     */
533
    public function failureCount()
534
    {
535
        return count($this->failures);
536
    }
537
538
    /**
539
     * Returns an Enumeration for the failures.
540
     *
541
     * @return array
542
     */
543
    public function failures()
544
    {
545
        return $this->failures;
546
    }
547
548
    /**
549
     * Gets the number of detected warnings.
550
     *
551
     * @return int
552
     */
553
    public function warningCount()
554
    {
555
        return count($this->warnings);
556
    }
557
558
    /**
559
     * Returns an Enumeration for the warnings.
560
     *
561
     * @return array
562
     */
563
    public function warnings()
564
    {
565
        return $this->warnings;
566
    }
567
568
    /**
569
     * Returns the names of the tests that have passed.
570
     *
571
     * @return array
572
     */
573
    public function passed()
574
    {
575
        return $this->passed;
576
    }
577
578
    /**
579
     * Returns the (top) test suite.
580
     *
581
     * @return PHPUnit_Framework_TestSuite
582
     */
583
    public function topTestSuite()
584
    {
585
        return $this->topTestSuite;
586
    }
587
588
    /**
589
     * Returns whether code coverage information should be collected.
590
     *
591
     * @return bool If code coverage should be collected
592
     */
593
    public function getCollectCodeCoverageInformation()
594
    {
595
        return $this->codeCoverage !== null;
596
    }
597
598
    /**
599
     * Runs a TestCase.
600
     *
601
     * @param PHPUnit_Framework_Test $test
602
     */
603
    public function run(PHPUnit_Framework_Test $test)
604
    {
605
        PHPUnit_Framework_Assert::resetCount();
606
607
        $coversNothing = false;
608
609
        if ($test instanceof PHPUnit_Framework_TestCase) {
610
            $test->setRegisterMockObjectsFromTestArgumentsRecursively(
611
                $this->registerMockObjectsFromTestArgumentsRecursively
612
            );
613
614
            $annotations = $test->getAnnotations();
615
616
            if (isset($annotations['class']['coversNothing']) || isset($annotations['method']['coversNothing'])) {
617
                $coversNothing = true;
618
            }
619
        }
620
621
        $error      = false;
622
        $failure    = false;
623
        $warning    = false;
624
        $incomplete = false;
625
        $risky      = false;
626
        $skipped    = false;
627
628
        $this->startTest($test);
629
630
        $errorHandlerSet = false;
631
632
        if ($this->convertErrorsToExceptions) {
633
            $oldErrorHandler = set_error_handler(
634
                ['PHPUnit_Util_ErrorHandler', 'handleError'],
635
                E_ALL | E_STRICT
636
            );
637
638
            if ($oldErrorHandler === null) {
639
                $errorHandlerSet = true;
640
            } else {
641
                restore_error_handler();
642
            }
643
        }
644
645
        $collectCodeCoverage = $this->codeCoverage !== null &&
646
                               !$test instanceof PHPUnit_Framework_WarningTestCase &&
647
                               !$coversNothing;
648
649
        if ($collectCodeCoverage) {
650
            $this->codeCoverage->start($test);
651
        }
652
653
        $monitorFunctions = $this->beStrictAboutResourceUsageDuringSmallTests &&
654
                            !$test instanceof PHPUnit_Framework_WarningTestCase &&
655
                            $test->getSize() == PHPUnit_Util_Test::SMALL &&
656
                            function_exists('xdebug_start_function_monitor');
657
658
        if ($monitorFunctions) {
659
            xdebug_start_function_monitor(ResourceOperations::getFunctions());
660
        }
661
662
        PHP_Timer::start();
663
664
        try {
665
            if (!$test instanceof PHPUnit_Framework_WarningTestCase &&
666
                $test->getSize() != PHPUnit_Util_Test::UNKNOWN &&
667
                $this->enforceTimeLimit &&
668
                extension_loaded('pcntl') && class_exists('PHP_Invoker')) {
669
                switch ($test->getSize()) {
670
                    case PHPUnit_Util_Test::SMALL:
671
                        $_timeout = $this->timeoutForSmallTests;
672
                        break;
673
674
                    case PHPUnit_Util_Test::MEDIUM:
675
                        $_timeout = $this->timeoutForMediumTests;
676
                        break;
677
678
                    case PHPUnit_Util_Test::LARGE:
679
                        $_timeout = $this->timeoutForLargeTests;
680
                        break;
681
                }
682
683
                $invoker = new PHP_Invoker;
684
                $invoker->invoke([$test, 'runBare'], [], $_timeout);
685
            } else {
686
                $test->runBare();
687
            }
688
        } catch (PHP_Invoker_TimeoutException $e) {
689
            $this->addFailure(
690
                $test,
691
                new PHPUnit_Framework_RiskyTestError(
692
                    $e->getMessage()
693
                ),
694
                $_timeout
695
            );
696
697
            $risky = true;
698
        } catch (PHPUnit_Framework_MockObject_Exception $e) {
699
            $e = new PHPUnit_Framework_Warning(
700
                $e->getMessage()
701
            );
702
703
            $warning = true;
704
        } catch (PHPUnit_Framework_AssertionFailedError $e) {
705
            $failure = true;
706
707
            if ($e instanceof PHPUnit_Framework_RiskyTestError) {
708
                $risky = true;
709
            } elseif ($e instanceof PHPUnit_Framework_IncompleteTestError) {
710
                $incomplete = true;
711
            } elseif ($e instanceof PHPUnit_Framework_SkippedTestError) {
712
                $skipped = true;
713
            }
714
        } catch (PHPUnit_Framework_Warning $e) {
715
            $warning = true;
716
        } catch (PHPUnit_Framework_Exception $e) {
717
            $error = true;
718
        } catch (Throwable $e) {
719
            // @see https://github.com/sebastianbergmann/phpunit/issues/2394
720
            if (PHP_MAJOR_VERSION === 7 && $e instanceof \AssertionError) {
721
                $test->addToAssertionCount(1);
722
723
                $failure = true;
724
                $frame   = $e->getTrace()[0];
725
726
                $e = new PHPUnit_Framework_AssertionFailedError(
727
                    sprintf(
728
                        '%s in %s:%s',
729
                        $e->getMessage(),
730
                        $frame['file'],
731
                        $frame['line']
732
                    )
733
                );
734
            } else {
735
                $e     = new PHPUnit_Framework_ExceptionWrapper($e);
736
                $error = true;
737
            }
738
        } catch (Exception $e) {
739
            $e     = new PHPUnit_Framework_ExceptionWrapper($e);
740
            $error = true;
741
        }
742
743
        $time = PHP_Timer::stop();
744
        $test->addToAssertionCount(PHPUnit_Framework_Assert::getCount());
745
746
        if ($monitorFunctions) {
747
            $blacklist = new PHPUnit_Util_Blacklist;
748
            $functions = xdebug_get_monitored_functions();
749
            xdebug_stop_function_monitor();
750
751
            foreach ($functions as $function) {
752
                if (!$blacklist->isBlacklisted($function['filename'])) {
753
                    $this->addFailure(
754
                        $test,
755
                        new PHPUnit_Framework_RiskyTestError(
756
                            sprintf(
757
                                '%s() used in %s:%s',
758
                                $function['function'],
759
                                $function['filename'],
760
                                $function['lineno']
761
                            )
762
                        ),
763
                        $time
764
                    );
765
                }
766
            }
767
        }
768
769
        if ($this->beStrictAboutTestsThatDoNotTestAnything &&
770
            $test->getNumAssertions() == 0) {
771
            $risky = true;
772
        }
773
774
        if ($collectCodeCoverage) {
775
            $append           = !$risky && !$incomplete && !$skipped;
776
            $linesToBeCovered = [];
777
            $linesToBeUsed    = [];
778
779
            if ($append && $test instanceof PHPUnit_Framework_TestCase) {
780
                try {
781
                    $linesToBeCovered = PHPUnit_Util_Test::getLinesToBeCovered(
782
                        get_class($test),
783
                        $test->getName(false)
784
                    );
785
786
                    $linesToBeUsed = PHPUnit_Util_Test::getLinesToBeUsed(
787
                        get_class($test),
788
                        $test->getName(false)
789
                    );
790
                } catch (PHPUnit_Framework_InvalidCoversTargetException $cce) {
791
                    $this->addWarning(
792
                        $test,
793
                        new PHPUnit_Framework_Warning(
794
                            $cce->getMessage()
795
                        ),
796
                        $time
797
                    );
798
                }
799
            }
800
801
            try {
802
                $this->codeCoverage->stop(
803
                    $append,
804
                    $linesToBeCovered,
805
                    $linesToBeUsed
806
                );
807
            } catch (UnintentionallyCoveredCodeException $cce) {
808
                $this->addFailure(
809
                    $test,
810
                    new PHPUnit_Framework_UnintentionallyCoveredCodeError(
811
                        'This test executed code that is not listed as code to be covered or used:' .
812
                        PHP_EOL . $cce->getMessage()
813
                    ),
814
                    $time
815
                );
816
            } catch (CoveredCodeNotExecutedException $cce) {
817
                $this->addFailure(
818
                    $test,
819
                    new PHPUnit_Framework_CoveredCodeNotExecutedException(
820
                        'This test did not execute all the code that is listed as code to be covered:' .
821
                        PHP_EOL . $cce->getMessage()
822
                    ),
823
                    $time
824
                );
825
            } catch (MissingCoversAnnotationException $cce) {
826
                if ($linesToBeCovered !== false) {
827
                    $this->addFailure(
828
                        $test,
829
                        new PHPUnit_Framework_MissingCoversAnnotationException(
830
                            'This test does not have a @covers annotation but is expected to have one'
831
                        ),
832
                        $time
833
                    );
834
                }
835
            } catch (CodeCoverageException $cce) {
836
                $error = true;
837
838
                if (!isset($e)) {
839
                    $e = $cce;
840
                }
841
            }
842
        }
843
844
        if ($errorHandlerSet === true) {
845
            restore_error_handler();
846
        }
847
848
        if ($error === true) {
849
            $this->addError($test, $e, $time);
850
        } elseif ($failure === true) {
851
            $this->addFailure($test, $e, $time);
852
        } elseif ($warning === true) {
853
            $this->addWarning($test, $e, $time);
854
        } elseif ($this->beStrictAboutTestsThatDoNotTestAnything &&
855
                  !$test->doesNotPerformAssertions() &&
856
                  $test->getNumAssertions() == 0) {
857
            $this->addFailure(
858
                $test,
859
                new PHPUnit_Framework_RiskyTestError(
860
                    'This test did not perform any assertions'
861
                ),
862
                $time
863
            );
864
        } elseif ($this->beStrictAboutOutputDuringTests && $test->hasOutput()) {
865
            $this->addFailure(
866
                $test,
867
                new PHPUnit_Framework_OutputError(
868
                    sprintf(
869
                        'This test printed output: %s',
870
                        $test->getActualOutput()
871
                    )
872
                ),
873
                $time
874
            );
875
        } elseif ($this->beStrictAboutTodoAnnotatedTests && $test instanceof PHPUnit_Framework_TestCase) {
876
            $annotations = $test->getAnnotations();
877
878
            if (isset($annotations['method']['todo'])) {
879
                $this->addFailure(
880
                    $test,
881
                    new PHPUnit_Framework_RiskyTestError(
882
                        'Test method is annotated with @todo'
883
                    ),
884
                    $time
885
                );
886
            }
887
        }
888
889
        $this->endTest($test, $time);
890
    }
891
892
    /**
893
     * Gets the number of run tests.
894
     *
895
     * @return int
896
     */
897
    public function count()
898
    {
899
        return $this->runTests;
900
    }
901
902
    /**
903
     * Checks whether the test run should stop.
904
     *
905
     * @return bool
906
     */
907
    public function shouldStop()
908
    {
909
        return $this->stop;
910
    }
911
912
    /**
913
     * Marks that the test run should stop.
914
     */
915
    public function stop()
916
    {
917
        $this->stop = true;
918
    }
919
920
    /**
921
     * Returns the code coverage object.
922
     *
923
     * @return CodeCoverage
924
     */
925
    public function getCodeCoverage()
926
    {
927
        return $this->codeCoverage;
928
    }
929
930
    /**
931
     * Sets the code coverage object.
932
     *
933
     * @param CodeCoverage $codeCoverage
934
     */
935
    public function setCodeCoverage(CodeCoverage $codeCoverage)
936
    {
937
        $this->codeCoverage = $codeCoverage;
938
    }
939
940
    /**
941
     * Enables or disables the error-to-exception conversion.
942
     *
943
     * @param bool $flag
944
     *
945
     * @throws PHPUnit_Framework_Exception
946
     */
947
    public function convertErrorsToExceptions($flag)
948
    {
949
        if (!is_bool($flag)) {
950
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
951
        }
952
953
        $this->convertErrorsToExceptions = $flag;
954
    }
955
956
    /**
957
     * Returns the error-to-exception conversion setting.
958
     *
959
     * @return bool
960
     */
961
    public function getConvertErrorsToExceptions()
962
    {
963
        return $this->convertErrorsToExceptions;
964
    }
965
966
    /**
967
     * Enables or disables the stopping when an error occurs.
968
     *
969
     * @param bool $flag
970
     *
971
     * @throws PHPUnit_Framework_Exception
972
     */
973
    public function stopOnError($flag)
974
    {
975
        if (!is_bool($flag)) {
976
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
977
        }
978
979
        $this->stopOnError = $flag;
980
    }
981
982
    /**
983
     * Enables or disables the stopping when a failure occurs.
984
     *
985
     * @param bool $flag
986
     *
987
     * @throws PHPUnit_Framework_Exception
988
     */
989
    public function stopOnFailure($flag)
990
    {
991
        if (!is_bool($flag)) {
992
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
993
        }
994
995
        $this->stopOnFailure = $flag;
996
    }
997
998
    /**
999
     * Enables or disables the stopping when a warning occurs.
1000
     *
1001
     * @param bool $flag
1002
     *
1003
     * @throws PHPUnit_Framework_Exception
1004
     */
1005
    public function stopOnWarning($flag)
1006
    {
1007
        if (!is_bool($flag)) {
1008
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
1009
        }
1010
1011
        $this->stopOnWarning = $flag;
1012
    }
1013
1014
    /**
1015
     * @param bool $flag
1016
     *
1017
     * @throws PHPUnit_Framework_Exception
1018
     */
1019
    public function beStrictAboutTestsThatDoNotTestAnything($flag)
1020
    {
1021
        if (!is_bool($flag)) {
1022
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
1023
        }
1024
1025
        $this->beStrictAboutTestsThatDoNotTestAnything = $flag;
1026
    }
1027
1028
    /**
1029
     * @return bool
1030
     */
1031
    public function isStrictAboutTestsThatDoNotTestAnything()
1032
    {
1033
        return $this->beStrictAboutTestsThatDoNotTestAnything;
1034
    }
1035
1036
    /**
1037
     * @param bool $flag
1038
     *
1039
     * @throws PHPUnit_Framework_Exception
1040
     */
1041
    public function beStrictAboutOutputDuringTests($flag)
1042
    {
1043
        if (!is_bool($flag)) {
1044
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
1045
        }
1046
1047
        $this->beStrictAboutOutputDuringTests = $flag;
1048
    }
1049
1050
    /**
1051
     * @return bool
1052
     */
1053
    public function isStrictAboutOutputDuringTests()
1054
    {
1055
        return $this->beStrictAboutOutputDuringTests;
1056
    }
1057
1058
    /**
1059
     * @param bool $flag
1060
     *
1061
     * @throws PHPUnit_Framework_Exception
1062
     */
1063
    public function beStrictAboutResourceUsageDuringSmallTests($flag)
1064
    {
1065
        if (!is_bool($flag)) {
1066
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
1067
        }
1068
1069
        $this->beStrictAboutResourceUsageDuringSmallTests = $flag;
1070
    }
1071
1072
    /**
1073
     * @return bool
1074
     */
1075
    public function isStrictAboutResourceUsageDuringSmallTests()
1076
    {
1077
        return $this->beStrictAboutResourceUsageDuringSmallTests;
1078
    }
1079
1080
    /**
1081
     * @param bool $flag
1082
     *
1083
     * @throws PHPUnit_Framework_Exception
1084
     */
1085
    public function enforceTimeLimit($flag)
1086
    {
1087
        if (!is_bool($flag)) {
1088
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
1089
        }
1090
1091
        $this->enforceTimeLimit = $flag;
1092
    }
1093
1094
    /**
1095
     * @return bool
1096
     */
1097
    public function enforcesTimeLimit()
1098
    {
1099
        return $this->enforceTimeLimit;
1100
    }
1101
1102
    /**
1103
     * @param bool $flag
1104
     *
1105
     * @throws PHPUnit_Framework_Exception
1106
     */
1107
    public function beStrictAboutTodoAnnotatedTests($flag)
1108
    {
1109
        if (!is_bool($flag)) {
1110
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
1111
        }
1112
1113
        $this->beStrictAboutTodoAnnotatedTests = $flag;
1114
    }
1115
1116
    /**
1117
     * @return bool
1118
     */
1119
    public function isStrictAboutTodoAnnotatedTests()
1120
    {
1121
        return $this->beStrictAboutTodoAnnotatedTests;
1122
    }
1123
1124
    /**
1125
     * Enables or disables the stopping for risky tests.
1126
     *
1127
     * @param bool $flag
1128
     *
1129
     * @throws PHPUnit_Framework_Exception
1130
     */
1131
    public function stopOnRisky($flag)
1132
    {
1133
        if (!is_bool($flag)) {
1134
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
1135
        }
1136
1137
        $this->stopOnRisky = $flag;
1138
    }
1139
1140
    /**
1141
     * Enables or disables the stopping for incomplete tests.
1142
     *
1143
     * @param bool $flag
1144
     *
1145
     * @throws PHPUnit_Framework_Exception
1146
     */
1147
    public function stopOnIncomplete($flag)
1148
    {
1149
        if (!is_bool($flag)) {
1150
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
1151
        }
1152
1153
        $this->stopOnIncomplete = $flag;
1154
    }
1155
1156
    /**
1157
     * Enables or disables the stopping for skipped tests.
1158
     *
1159
     * @param bool $flag
1160
     *
1161
     * @throws PHPUnit_Framework_Exception
1162
     */
1163
    public function stopOnSkipped($flag)
1164
    {
1165
        if (!is_bool($flag)) {
1166
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
1167
        }
1168
1169
        $this->stopOnSkipped = $flag;
1170
    }
1171
1172
    /**
1173
     * Returns the time spent running the tests.
1174
     *
1175
     * @return float
1176
     */
1177
    public function time()
1178
    {
1179
        return $this->time;
1180
    }
1181
1182
    /**
1183
     * Returns whether the entire test was successful or not.
1184
     *
1185
     * @param bool $includeWarnings
1186
     *
1187
     * @return bool
1188
     */
1189
    public function wasSuccessful($includeWarnings = true)
1190
    {
1191
        if ($includeWarnings) {
1192
            return empty($this->errors) && empty($this->failures) && empty($this->warnings);
1193
        } else {
1194
            return empty($this->errors) && empty($this->failures);
1195
        }
1196
    }
1197
1198
    /**
1199
     * Sets the timeout for small tests.
1200
     *
1201
     * @param int $timeout
1202
     *
1203
     * @throws PHPUnit_Framework_Exception
1204
     */
1205
    public function setTimeoutForSmallTests($timeout)
1206
    {
1207
        if (!is_int($timeout)) {
1208
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'integer');
1209
        }
1210
1211
        $this->timeoutForSmallTests = $timeout;
1212
    }
1213
1214
    /**
1215
     * Sets the timeout for medium tests.
1216
     *
1217
     * @param int $timeout
1218
     *
1219
     * @throws PHPUnit_Framework_Exception
1220
     */
1221
    public function setTimeoutForMediumTests($timeout)
1222
    {
1223
        if (!is_int($timeout)) {
1224
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'integer');
1225
        }
1226
1227
        $this->timeoutForMediumTests = $timeout;
1228
    }
1229
1230
    /**
1231
     * Sets the timeout for large tests.
1232
     *
1233
     * @param int $timeout
1234
     *
1235
     * @throws PHPUnit_Framework_Exception
1236
     */
1237
    public function setTimeoutForLargeTests($timeout)
1238
    {
1239
        if (!is_int($timeout)) {
1240
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'integer');
1241
        }
1242
1243
        $this->timeoutForLargeTests = $timeout;
1244
    }
1245
1246
    /**
1247
     * Returns the set timeout for large tests.
1248
     *
1249
     * @return int
1250
     */
1251
    public function getTimeoutForLargeTests()
1252
    {
1253
        return $this->timeoutForLargeTests;
1254
    }
1255
1256
    /**
1257
     * @param bool $flag
1258
     */
1259
    public function setRegisterMockObjectsFromTestArgumentsRecursively($flag)
1260
    {
1261
        if (!is_bool($flag)) {
1262
            throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
1263
        }
1264
1265
        $this->registerMockObjectsFromTestArgumentsRecursively = $flag;
1266
    }
1267
1268
    /**
1269
     * Returns the class hierarchy for a given class.
1270
     *
1271
     * @param string $className
1272
     * @param bool   $asReflectionObjects
1273
     *
1274
     * @return array
1275
     */
1276
    protected function getHierarchy($className, $asReflectionObjects = false)
1277
    {
1278
        if ($asReflectionObjects) {
1279
            $classes = [new ReflectionClass($className)];
1280
        } else {
1281
            $classes = [$className];
1282
        }
1283
1284
        $done = false;
1285
1286
        while (!$done) {
1287
            if ($asReflectionObjects) {
1288
                $class = new ReflectionClass(
1289
                    $classes[count($classes) - 1]->getName()
1290
                );
1291
            } else {
1292
                $class = new ReflectionClass($classes[count($classes) - 1]);
1293
            }
1294
1295
            $parent = $class->getParentClass();
1296
1297
            if ($parent !== false) {
1298
                if ($asReflectionObjects) {
1299
                    $classes[] = $parent;
1300
                } else {
1301
                    $classes[] = $parent->getName();
1302
                }
1303
            } else {
1304
                $done = true;
1305
            }
1306
        }
1307
1308
        return $classes;
1309
    }
1310
}
1311