5 * Copyright (c) 2002-2011, Sebastian Bergmann <sebastian@phpunit.de>.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
20 * * Neither the name of Sebastian Bergmann nor the names of his
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
38 * @subpackage Framework
39 * @author Sebastian Bergmann <sebastian@phpunit.de>
40 * @copyright 2002-2011 Sebastian Bergmann <sebastian@phpunit.de>
41 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42 * @link http://www.phpunit.de/
43 * @since File available since Release 2.0.0
46 require_once 'PHP/CodeCoverage.php';
47 require_once 'PHP/Timer.php';
50 * A TestResult collects the results of executing a test case.
53 * @subpackage Framework
54 * @author Sebastian Bergmann <sebastian@phpunit.de>
55 * @copyright 2002-2011 Sebastian Bergmann <sebastian@phpunit.de>
56 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
57 * @version Release: 3.5.13
58 * @link http://www.phpunit.de/
59 * @since Class available since Release 2.0.0
61 class PHPUnit_Framework_TestResult implements Countable
66 protected static $xdebugLoaded = NULL;
71 protected static $useXdebug = NULL;
76 protected $passed = array();
81 protected $errors = array();
86 protected $deprecatedFeatures = array();
91 protected $failures = array();
96 protected $notImplemented = array();
101 protected $skipped = array();
106 protected $listeners = array();
111 protected $runTests = 0;
119 * @var PHPUnit_Framework_TestSuite
121 protected $topTestSuite = NULL;
124 * Code Coverage information.
128 protected $codeCoverage;
133 protected $collectCodeCoverageInformation = FALSE;
138 protected $collectRawCodeCoverageInformation = FALSE;
143 protected $rawCodeCoverageInformation = array();
148 protected $convertErrorsToExceptions = TRUE;
153 protected $stop = FALSE;
158 protected $stopOnError = FALSE;
163 protected $stopOnFailure = FALSE;
168 protected $strictMode = FALSE;
173 protected $stopOnIncomplete = FALSE;
178 protected $stopOnSkipped = FALSE;
183 protected $lastTestFailed = FALSE;
186 * @param PHP_CodeCoverage $codeCoverage
188 public function __construct(PHP_CodeCoverage $codeCoverage = NULL)
190 if ($codeCoverage === NULL) {
191 $codeCoverage = PHP_CodeCoverage::getInstance();
194 $this->codeCoverage = $codeCoverage;
198 * Registers a TestListener.
200 * @param PHPUnit_Framework_TestListener
202 public function addListener(PHPUnit_Framework_TestListener $listener)
204 $this->listeners[] = $listener;
208 * Unregisters a TestListener.
210 * @param PHPUnit_Framework_TestListener $listener
212 public function removeListener(PHPUnit_Framework_TestListener $listener)
214 foreach ($this->listeners as $key => $_listener) {
215 if ($listener === $_listener) {
216 unset($this->listeners[$key]);
222 * Flushes all flushable TestListeners.
224 * @since Method available since Release 3.0.0
226 public function flushListeners()
228 foreach ($this->listeners as $listener) {
229 if ($listener instanceof PHPUnit_Util_Printer) {
236 * Adds an error to the list of errors.
238 * @param PHPUnit_Framework_Test $test
239 * @param Exception $e
242 public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)
244 if ($e instanceof PHPUnit_Framework_IncompleteTest) {
245 $this->notImplemented[] = new PHPUnit_Framework_TestFailure(
249 $notifyMethod = 'addIncompleteTest';
251 if ($this->stopOnIncomplete) {
256 else if ($e instanceof PHPUnit_Framework_SkippedTest) {
257 $this->skipped[] = new PHPUnit_Framework_TestFailure($test, $e);
258 $notifyMethod = 'addSkippedTest';
260 if ($this->stopOnSkipped) {
266 $this->errors[] = new PHPUnit_Framework_TestFailure($test, $e);
267 $notifyMethod = 'addError';
269 if ($this->stopOnError || $this->stopOnFailure) {
274 foreach ($this->listeners as $listener) {
275 $listener->$notifyMethod($test, $e, $time);
278 $this->lastTestFailed = TRUE;
279 $this->time += $time;
283 * Adds a failure to the list of failures.
284 * The passed in exception caused the failure.
286 * @param PHPUnit_Framework_Test $test
287 * @param PHPUnit_Framework_AssertionFailedError $e
290 public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)
292 if ($e instanceof PHPUnit_Framework_IncompleteTest) {
293 $this->notImplemented[] = new PHPUnit_Framework_TestFailure(
297 $notifyMethod = 'addIncompleteTest';
299 if ($this->stopOnIncomplete) {
304 else if ($e instanceof PHPUnit_Framework_SkippedTest) {
305 $this->skipped[] = new PHPUnit_Framework_TestFailure($test, $e);
306 $notifyMethod = 'addSkippedTest';
308 if ($this->stopOnSkipped) {
314 $this->failures[] = new PHPUnit_Framework_TestFailure($test, $e);
315 $notifyMethod = 'addFailure';
317 if ($this->stopOnFailure) {
322 foreach ($this->listeners as $listener) {
323 $listener->$notifyMethod($test, $e, $time);
326 $this->lastTestFailed = TRUE;
327 $this->time += $time;
331 * Adds a deprecated feature notice to the list of deprecated features used during run
333 * @param PHPUnit_Util_DeprecatedFeature $deprecatedFeature
335 public function addDeprecatedFeature(PHPUnit_Util_DeprecatedFeature $deprecatedFeature)
337 $this->deprecatedFeatures[] = $deprecatedFeature;
341 * Informs the result that a testsuite will be started.
343 * @param PHPUnit_Framework_TestSuite $suite
344 * @since Method available since Release 2.2.0
346 public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
348 if ($this->topTestSuite === NULL) {
349 $this->topTestSuite = $suite;
352 foreach ($this->listeners as $listener) {
353 $listener->startTestSuite($suite);
358 * Informs the result that a testsuite was completed.
360 * @param PHPUnit_Framework_TestSuite $suite
361 * @since Method available since Release 2.2.0
363 public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
365 foreach ($this->listeners as $listener) {
366 $listener->endTestSuite($suite);
371 * Informs the result that a test will be started.
373 * @param PHPUnit_Framework_Test $test
375 public function startTest(PHPUnit_Framework_Test $test)
377 $this->lastTestFailed = FALSE;
378 $this->runTests += count($test);
380 foreach ($this->listeners as $listener) {
381 $listener->startTest($test);
386 * Informs the result that a test was completed.
388 * @param PHPUnit_Framework_Test $test
391 public function endTest(PHPUnit_Framework_Test $test, $time)
393 foreach ($this->listeners as $listener) {
394 $listener->endTest($test, $time);
397 if (!$this->lastTestFailed && $test instanceof PHPUnit_Framework_TestCase) {
398 $this->passed[get_class($test) . '::' . $test->getName()] = $test->getResult();
399 $this->time += $time;
404 * Returns TRUE if no incomplete test occured.
408 public function allCompletlyImplemented()
410 return $this->notImplementedCount() == 0;
414 * Gets the number of incomplete tests.
418 public function notImplementedCount()
420 return count($this->notImplemented);
424 * Returns an Enumeration for the incomplete tests.
428 public function notImplemented()
430 return $this->notImplemented;
434 * Returns TRUE if no test has been skipped.
437 * @since Method available since Release 3.0.0
439 public function noneSkipped()
441 return $this->skippedCount() == 0;
445 * Gets the number of skipped tests.
448 * @since Method available since Release 3.0.0
450 public function skippedCount()
452 return count($this->skipped);
456 * Returns an Enumeration for the skipped tests.
459 * @since Method available since Release 3.0.0
461 public function skipped()
463 return $this->skipped;
467 * Gets the number of detected errors.
471 public function errorCount()
473 return count($this->errors);
477 * Returns an Enumeration for the errors.
481 public function errors()
483 return $this->errors;
487 * Returns an Enumeration for the deprecated features used.
490 * @since Method available since Release 3.5.7
492 public function deprecatedFeatures()
494 return $this->deprecatedFeatures;
498 * Returns an Enumeration for the deprecated features used.
501 * @since Method available since Release 3.5.7
503 public function deprecatedFeaturesCount()
505 return count($this->deprecatedFeatures);
509 * Gets the number of detected failures.
513 public function failureCount()
515 return count($this->failures);
519 * Returns an Enumeration for the failures.
523 public function failures()
525 return $this->failures;
529 * Returns the names of the tests that have passed.
532 * @since Method available since Release 3.4.0
534 public function passed()
536 return $this->passed;
540 * Returns the (top) test suite.
542 * @return PHPUnit_Framework_TestSuite
543 * @since Method available since Release 3.0.0
545 public function topTestSuite()
547 return $this->topTestSuite;
551 * Enables or disables the collection of Code Coverage information.
553 * @param boolean $flag
554 * @throws InvalidArgumentException
555 * @since Method available since Release 2.3.0
557 public function collectCodeCoverageInformation($flag)
559 if (is_bool($flag)) {
560 $this->collectCodeCoverageInformation = $flag;
562 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
567 * Enables or disables the collection of raw Code Coverage information.
569 * @param boolean $flag
570 * @throws InvalidArgumentException
571 * @since Method available since Release 3.4.0
573 public function collectRawCodeCoverageInformation($flag)
575 if (is_bool($flag)) {
576 $this->collectRawCodeCoverageInformation = $flag;
578 if ($flag === TRUE) {
579 $this->collectCodeCoverageInformation = $flag;
582 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
587 * Returns whether code coverage information should be collected.
589 * @return boolean If code coverage should be collected
590 * @since Method available since Release 3.2.0
592 public function getCollectCodeCoverageInformation()
594 return $this->collectCodeCoverageInformation;
598 * Returns the raw Code Coverage information.
601 * @since Method available since Release 3.4.0
603 public function getRawCodeCoverageInformation()
605 return $this->rawCodeCoverageInformation;
609 * Returns the strict mode configuration option
613 public function isStrict()
615 return $this->strictMode;
621 * @param PHPUnit_Framework_Test $test
623 public function run(PHPUnit_Framework_Test $test)
625 PHPUnit_Framework_Assert::resetCount();
632 $this->startTest($test);
634 $errorHandlerSet = FALSE;
636 if ($this->convertErrorsToExceptions) {
637 $oldErrorHandler = set_error_handler(
638 array('PHPUnit_Util_ErrorHandler', 'handleError'),
642 if ($oldErrorHandler === NULL) {
643 $errorHandlerSet = TRUE;
645 restore_error_handler();
649 if (self::$xdebugLoaded === NULL) {
650 self::$xdebugLoaded = extension_loaded('xdebug');
651 self::$useXdebug = self::$xdebugLoaded;
654 $useXdebug = self::$useXdebug &&
655 $this->collectCodeCoverageInformation &&
656 !$test instanceof PHPUnit_Extensions_SeleniumTestCase &&
657 !$test instanceof PHPUnit_Framework_Warning;
660 $this->codeCoverage->start($test);
669 catch (PHPUnit_Framework_AssertionFailedError $e) {
672 if ($e instanceof PHPUnit_Framework_IncompleteTestError) {
676 else if ($e instanceof PHPUnit_Framework_SkippedTestError) {
681 catch (Exception $e) {
685 $time = PHP_Timer::stop();
686 $test->addToAssertionCount(PHPUnit_Framework_Assert::getCount());
688 if ($this->strictMode && $test->getNumAssertions() == 0) {
693 $data = $this->codeCoverage->stop(FALSE);
695 if (!$incomplete && !$skipped) {
696 if ($this->collectRawCodeCoverageInformation) {
697 $this->rawCodeCoverageInformation[] = $data;
699 $filterGroups = array('DEFAULT', 'TESTS');
701 if (!defined('PHPUNIT_TESTSUITE')) {
702 $filterGroups[] = 'PHPUNIT';
705 $this->codeCoverage->append($data, $test, $filterGroups);
712 if ($errorHandlerSet === TRUE) {
713 restore_error_handler();
716 if ($error === TRUE) {
717 $this->addError($test, $e, $time);
720 else if ($failure === TRUE) {
721 $this->addFailure($test, $e, $time);
724 else if ($this->strictMode && $test->getNumAssertions() == 0) {
727 new PHPUnit_Framework_IncompleteTestError(
728 'This test did not perform any assertions'
734 $this->endTest($test, $time);
738 * Gets the number of run tests.
742 public function count()
744 return $this->runTests;
748 * Checks whether the test run should stop.
752 public function shouldStop()
758 * Marks that the test run should stop.
761 public function stop()
767 * Returns the PHP_CodeCoverage object.
769 * @return PHP_CodeCoverage
770 * @since Method available since Release 3.5.0
772 public function getCodeCoverage()
774 return $this->codeCoverage;
778 * Enables or disables the error-to-exception conversion.
780 * @param boolean $flag
781 * @throws InvalidArgumentException
782 * @since Method available since Release 3.2.14
784 public function convertErrorsToExceptions($flag)
786 if (is_bool($flag)) {
787 $this->convertErrorsToExceptions = $flag;
789 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
794 * Returns the error-to-exception conversion setting.
797 * @since Method available since Release 3.4.0
799 public function getConvertErrorsToExceptions()
801 return $this->convertErrorsToExceptions;
805 * Enables or disables the stopping when an error occurs.
807 * @param boolean $flag
808 * @throws InvalidArgumentException
809 * @since Method available since Release 3.5.0
811 public function stopOnError($flag)
813 if (is_bool($flag)) {
814 $this->stopOnError = $flag;
816 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
821 * Enables or disables the stopping when a failure occurs.
823 * @param boolean $flag
824 * @throws InvalidArgumentException
825 * @since Method available since Release 3.1.0
827 public function stopOnFailure($flag)
829 if (is_bool($flag)) {
830 $this->stopOnFailure = $flag;
832 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
837 * Enables or disables the strict mode.
840 * * Tests that do not assert anything will be marked as incomplete.
841 * * Tests that are incomplete or skipped yield no code coverage.
843 * @param boolean $flag
844 * @throws InvalidArgumentException
845 * @since Method available since Release 3.5.2
847 public function strictMode($flag)
849 if (is_bool($flag)) {
850 $this->strictMode = $flag;
852 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
857 * Enables or disables the stopping for incomplete tests.
859 * @param boolean $flag
860 * @throws InvalidArgumentException
861 * @since Method available since Release 3.5.0
863 public function stopOnIncomplete($flag)
865 if (is_bool($flag)) {
866 $this->stopOnIncomplete = $flag;
868 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
873 * Enables or disables the stopping for skipped tests.
875 * @param boolean $flag
876 * @throws InvalidArgumentException
877 * @since Method available since Release 3.1.0
879 public function stopOnSkipped($flag)
881 if (is_bool($flag)) {
882 $this->stopOnSkipped = $flag;
884 throw PHPUnit_Util_InvalidArgumentHelper::factory(1, 'boolean');
889 * Returns the time spent running the tests.
893 public function time()
899 * Returns whether the entire test was successful or not.
903 public function wasSuccessful()
905 return empty($this->errors) && empty($this->failures);