5 * Copyright (c) 2002-2009, Sebastian Bergmann <sb@sebastian-bergmann.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.
39 * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
40 * @copyright 2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
41 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43 * @link http://www.phpunit.de/
44 * @since File available since Release 2.0.0
47 require_once 'PHPUnit/Framework.php';
48 require_once 'PHPUnit/Framework/MockObject/Mock.php';
49 require_once 'PHPUnit/Framework/MockObject/Matcher/InvokedAtLeastOnce.php';
50 require_once 'PHPUnit/Framework/MockObject/Matcher/InvokedAtIndex.php';
51 require_once 'PHPUnit/Framework/MockObject/Matcher/InvokedCount.php';
52 require_once 'PHPUnit/Framework/MockObject/Stub.php';
53 require_once 'PHPUnit/Runner/BaseTestRunner.php';
54 require_once 'PHPUnit/Util/Filter.php';
56 PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
58 if (!class_exists('PHPUnit_Framework_TestCase', FALSE)) {
61 * A TestCase defines the fixture to run multiple tests.
63 * To define a TestCase
65 * 1) Implement a subclass of PHPUnit_Framework_TestCase.
66 * 2) Define instance variables that store the state of the fixture.
67 * 3) Initialize the fixture state by overriding setUp().
68 * 4) Clean-up after a test by overriding tearDown().
70 * Each test runs in its own fixture so there can be no side effects
77 * require_once 'PHPUnit/Framework/TestCase.php';
79 * class MathTest extends PHPUnit_Framework_TestCase
84 * protected function setUp()
93 * For each test implement a method which interacts with the fixture.
94 * Verify the expected results with assertions specified by calling
95 * assert with a boolean.
99 * public function testPass()
101 * $this->assertTrue($this->value1 + $this->value2 == 5);
108 * @author Sebastian Bergmann <sb@sebastian-bergmann.de>
109 * @copyright 2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
110 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
111 * @version Release: 3.3.17
112 * @link http://www.phpunit.de/
113 * @since Class available since Release 2.0.0
116 abstract class PHPUnit_Framework_TestCase extends PHPUnit_Framework_Assert implements PHPUnit_Framework_Test, PHPUnit_Framework_SelfDescribing
119 * Enable or disable the backup and restoration of the $GLOBALS array.
120 * Overwrite this attribute in a child class of TestCase.
121 * Setting this attribute in setUp() has no effect!
125 protected $backupGlobals = NULL;
130 protected $globalsBackup = array();
135 protected $data = array();
140 protected $dataName = '';
143 * The name of the expected Exception.
147 protected $expectedException = NULL;
150 * The message of the expected Exception.
154 protected $expectedExceptionMessage = '';
157 * The code of the expected Exception.
161 protected $expectedExceptionCode;
164 * Fixture that is shared between the tests of a test suite.
168 protected $sharedFixture;
171 * The name of the test case.
175 protected $name = NULL;
180 protected $exceptionMessage = NULL;
185 protected $exceptionCode = 0;
190 protected $iniSettings = array();
195 protected $locale = array();
200 protected $mockObjects = array();
210 protected $statusMessage = '';
215 protected $numAssertions = 0;
220 protected static $superGlobalArrays = array(
233 protected static $superGlobalArraysLong = array(
243 * Constructs a test case with the given name.
245 * @param string $name
247 * @param string $dataName
249 public function __construct($name = NULL, array $data = array(), $dataName = '')
251 if ($name !== NULL) {
252 $this->setName($name);
256 $this->dataName = $dataName;
260 * Returns a string representation of the test case.
264 public function toString()
266 $class = new ReflectionClass($this);
271 $this->getName(FALSE),
275 return $buffer . $this->getDataSetAsString();
279 * Counts the number of test cases executed by run(TestResult result).
283 public function count()
289 * Gets the name of a TestCase.
291 * @param boolean $withDataSet
294 public function getName($withDataSet = TRUE)
297 return $this->name . $this->getDataSetAsString(FALSE);
305 * @since Method available since Release 3.2.0
307 public function getExpectedException()
309 return $this->expectedException;
313 * @param mixed $exceptionName
314 * @param string $exceptionMessage
315 * @param integer $exceptionCode
316 * @since Method available since Release 3.2.0
318 public function setExpectedException($exceptionName, $exceptionMessage = '', $exceptionCode = 0)
320 $this->expectedException = $exceptionName;
321 $this->expectedExceptionMessage = $exceptionMessage;
322 $this->expectedExceptionCode = $exceptionCode;
326 * Returns the status of this test.
329 * @since Method available since Release 3.1.0
331 public function getStatus()
333 return $this->status;
337 * Returns the status message of this test.
340 * @since Method available since Release 3.3.0
342 public function getStatusMessage()
344 return $this->statusMessage;
348 * Returns whether or not this test has failed.
351 * @since Method available since Release 3.0.0
353 public function hasFailed()
355 $status = $this->getStatus();
357 return $status == PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE ||
358 $status == PHPUnit_Runner_BaseTestRunner::STATUS_ERROR;
362 * Runs the test case and collects the results in a TestResult object.
363 * If no TestResult object is passed a new one will be created.
365 * @param PHPUnit_Framework_TestResult $result
366 * @return PHPUnit_Framework_TestResult
367 * @throws InvalidArgumentException
369 public function run(PHPUnit_Framework_TestResult $result = NULL)
371 if ($result === NULL) {
372 $result = $this->createResult();
381 * Runs the bare test sequence.
384 public function runBare()
386 $this->numAssertions = 0;
388 // Backup the $GLOBALS array.
389 if ($this->backupGlobals === NULL || $this->backupGlobals === TRUE) {
390 $this->backupGlobals();
393 // Set up the fixture.
396 // Clean up stat cache.
401 // Assert pre-conditions.
402 $this->assertPreConditions();
406 // Assert post-conditions.
407 $this->assertPostConditions();
409 // Verify Mock Object conditions.
410 foreach ($this->mockObjects as $mockObject) {
411 $this->numAssertions++;
412 $mockObject->__phpunit_verify();
415 $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_PASSED;
418 catch (Exception $e) {
419 if ($e instanceof PHPUnit_Framework_IncompleteTest) {
420 $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE;
423 if ($e instanceof PHPUnit_Framework_SkippedTest) {
424 $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED;
427 if ($e instanceof PHPUnit_Framework_AssertionFailedError) {
428 $this->status = PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE;
431 $this->statusMessage = $e->getMessage();
434 $this->mockObjects = array();
436 // Tear down the fixture.
439 // Clean up stat cache.
442 // Restore the $GLOBALS array.
443 if ($this->backupGlobals === NULL || $this->backupGlobals === TRUE) {
444 $this->restoreGlobals();
447 // Clean up INI settings.
448 foreach ($this->iniSettings as $varName => $oldValue) {
449 ini_set($varName, $oldValue);
452 $this->iniSettings = array();
454 // Clean up locale settings.
455 foreach ($this->locale as $category => $locale) {
456 setlocale($category, $locale);
459 // Workaround for missing "finally".
466 * Override to run the test and assert its state.
468 * @throws RuntimeException
470 protected function runTest()
472 if ($this->name === NULL) {
473 throw new RuntimeException(
474 'PHPUnit_Framework_TestCase::$name must not be NULL.'
479 $class = new ReflectionClass($this);
480 $method = $class->getMethod($this->name);
483 catch (ReflectionException $e) {
484 $this->fail($e->getMessage());
488 if (empty($this->data)) {
489 $method->invoke($this);
491 $method->invokeArgs($this, $this->data);
495 catch (Exception $e) {
496 if (!$e instanceof PHPUnit_Framework_IncompleteTest &&
497 !$e instanceof PHPUnit_Framework_SkippedTest &&
498 is_string($this->expectedException) &&
499 $e instanceof $this->expectedException) {
500 if (is_string($this->expectedExceptionMessage) &&
501 !empty($this->expectedExceptionMessage)) {
502 $this->assertContains(
503 $this->expectedExceptionMessage,
508 if (is_int($this->expectedExceptionCode) &&
509 $this->expectedExceptionCode !== 0) {
511 $this->expectedExceptionCode, $e->getCode()
515 $this->numAssertions++;
523 if ($this->expectedException !== NULL) {
524 $this->numAssertions++;
525 $this->fail('Expected exception ' . $this->expectedException);
530 * Sets the name of a TestCase.
534 public function setName($name)
540 * Calling this method in setUp() has no effect!
542 * @param boolean $backupGlobals
543 * @since Method available since Release 3.3.0
545 public function setBackupGlobals($backupGlobals)
547 if (is_null($this->backupGlobals) && is_bool($backupGlobals)) {
548 $this->backupGlobals = $backupGlobals;
553 * Sets the shared fixture.
555 * @param mixed $sharedFixture
556 * @since Method available since Release 3.1.0
558 public function setSharedFixture($sharedFixture)
560 $this->sharedFixture = $sharedFixture;
564 * This method is a wrapper for the ini_set() function that automatically
565 * resets the modified php.ini setting to its original value after the
568 * @param string $varName
569 * @param string $newValue
570 * @throws InvalidArgumentException
571 * @throws RuntimeException
572 * @since Method available since Release 3.0.0
574 protected function iniSet($varName, $newValue)
576 if (!is_string($varName)) {
577 throw new InvalidArgumentException;
580 $currentValue = ini_set($varName, $newValue);
582 if ($currentValue !== FALSE) {
583 $this->iniSettings[$varName] = $currentValue;
585 throw new RuntimeException;
590 * This method is a wrapper for the setlocale() function that automatically
591 * resets the locale to its original value after the test is run.
593 * @param integer $category
594 * @param string $locale
595 * @throws InvalidArgumentException
596 * @throws RuntimeException
597 * @since Method available since Release 3.1.0
599 protected function setLocale()
601 $args = func_get_args();
603 if (count($args) < 2) {
604 throw new InvalidArgumentException;
607 $category = $args[0];
611 LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME
614 if (defined('LC_MESSAGES')) {
615 $categories[] = LC_MESSAGES;
618 if (!in_array($category, $categories)) {
619 throw new InvalidArgumentException;
622 if (!is_array($locale) && !is_string($locale)) {
623 throw new InvalidArgumentException;
626 $this->locale[$category] = setlocale($category, NULL);
628 $result = call_user_func_array( 'setlocale', $args );
630 if ($result === FALSE) {
631 throw new RuntimeException(
632 'The locale functionality is not implemented on your platform, ' .
633 'the specified locale does not exist or the category name is ' .
640 * Returns a mock object for the specified class.
642 * @param string $className
643 * @param array $methods
644 * @param array $arguments
645 * @param string $mockClassName
646 * @param boolean $callOriginalConstructor
647 * @param boolean $callOriginalClone
648 * @param boolean $callAutoload
650 * @since Method available since Release 3.0.0
652 protected function getMock($className, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE)
654 if (!is_string($className) || !is_string($mockClassName)) {
655 throw new InvalidArgumentException;
658 if (!is_array($methods) && !is_null($methods)) {
659 throw new InvalidArgumentException;
662 $mock = PHPUnit_Framework_MockObject_Mock::generate(
666 $callOriginalConstructor,
671 if (count($arguments) == 0) {
672 $mockObject = new $mock->mockClassName;
674 $mockClass = new ReflectionClass($mock->mockClassName);
675 $mockObject = $mockClass->newInstanceArgs($arguments);
678 $this->mockObjects[] = $mockObject;
684 * Adds a value to the assertion counter.
686 * @param integer $count
687 * @since Method available since Release 3.3.3
689 public function addToAssertionCount($count)
691 $this->numAssertions += $count;
695 * Returns the number of assertions performed by this test.
698 * @since Method available since Release 3.3.0
700 public function getNumAssertions()
702 return $this->numAssertions;
706 * Returns a matcher that matches when the method it is evaluated for
707 * is executed zero or more times.
709 * @return PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount
710 * @since Method available since Release 3.0.0
712 protected function any()
714 return new PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount;
718 * Returns a matcher that matches when the method it is evaluated for
721 * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount
722 * @since Method available since Release 3.0.0
724 protected function never()
726 return new PHPUnit_Framework_MockObject_Matcher_InvokedCount(0);
730 * Returns a matcher that matches when the method it is evaluated for
731 * is executed at least once.
733 * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce
734 * @since Method available since Release 3.0.0
736 protected function atLeastOnce()
738 return new PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce;
742 * Returns a matcher that matches when the method it is evaluated for
743 * is executed exactly once.
745 * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount
746 * @since Method available since Release 3.0.0
748 protected function once()
750 return new PHPUnit_Framework_MockObject_Matcher_InvokedCount(1);
754 * Returns a matcher that matches when the method it is evaluated for
755 * is executed exactly $count times.
757 * @param integer $count
758 * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount
759 * @since Method available since Release 3.0.0
761 protected function exactly($count)
763 return new PHPUnit_Framework_MockObject_Matcher_InvokedCount($count);
767 * Returns a matcher that matches when the method it is evaluated for
768 * is invoked at the given $index.
770 * @param integer $index
771 * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex
772 * @since Method available since Release 3.0.0
774 protected function at($index)
776 return new PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex($index);
782 * @param mixed $value
783 * @return PHPUnit_Framework_MockObject_Stub_Return
784 * @since Method available since Release 3.0.0
786 protected function returnValue($value)
788 return new PHPUnit_Framework_MockObject_Stub_Return($value);
794 * @param integer $argumentIndex
795 * @return PHPUnit_Framework_MockObject_Stub_ReturnArgument
796 * @since Method available since Release 3.3.0
798 protected function returnArgument($argumentIndex)
800 return new PHPUnit_Framework_MockObject_Stub_ReturnArgument($argumentIndex);
806 * @param mixed $callback
807 * @return PHPUnit_Framework_MockObject_Stub_ReturnCallback
808 * @since Method available since Release 3.3.0
810 protected function returnCallback($callback)
812 return new PHPUnit_Framework_MockObject_Stub_ReturnCallback($callback);
818 * @param Exception $exception
819 * @return PHPUnit_Framework_MockObject_Stub_Exception
820 * @since Method available since Release 3.1.0
822 protected function throwException(Exception $exception)
824 return new PHPUnit_Framework_MockObject_Stub_Exception($exception);
830 * @param mixed $value, ...
831 * @return PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls
832 * @since Method available since Release 3.0.0
834 protected function onConsecutiveCalls()
836 $args = func_get_args();
838 return new PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls($args);
844 * @since Method available since Release 3.2.1
846 protected function dataToString($data)
850 foreach ($data as $_data) {
851 if (is_array($_data)) {
852 $result[] = 'array(' . $this->dataToString($_data) . ')';
855 else if (is_object($_data)) {
856 $object = new ReflectionObject($_data);
858 if ($object->hasMethod('__toString')) {
859 $result[] = (string)$_data;
861 $result[] = get_class($_data);
865 else if (is_resource($_data)) {
866 $result[] = '<resource>';
870 $result[] = var_export($_data, TRUE);
874 return join(', ', $result);
878 * Gets the data set description of a TestCase.
880 * @param boolean $includeData
882 * @since Method available since Release 3.3.0
884 protected function getDataSetAsString($includeData = TRUE)
888 if (!empty($this->data)) {
889 if (is_int($this->dataName)) {
890 $buffer .= sprintf(' with data set #%d', $this->dataName);
892 $buffer .= sprintf(' with data set "%s"', $this->dataName);
896 $buffer .= sprintf(' (%s)', $this->dataToString($this->data));
904 * Creates a default TestResult object.
906 * @return PHPUnit_Framework_TestResult
908 protected function createResult()
910 return new PHPUnit_Framework_TestResult;
914 * Sets up the fixture, for example, open a network connection.
915 * This method is called before a test is executed.
918 protected function setUp()
923 * Performs assertions shared by all tests of a test case.
925 * This method is called before the execution of a test starts
926 * and after setUp() is called.
928 * @since Method available since Release 3.2.8
930 protected function assertPreConditions()
935 * Performs assertions shared by all tests of a test case.
937 * This method is called before the execution of a test ends
938 * and before tearDown() is called.
940 * @since Method available since Release 3.2.8
942 protected function assertPostConditions()
944 // assertPostConditions() was named sharedAssertions() in
945 // PHPUnit 3.0.0-3.2.7.
946 if (method_exists($this, 'sharedAssertions')) {
947 $this->sharedAssertions();
952 * Tears down the fixture, for example, close a network connection.
953 * This method is called after a test is executed.
955 protected function tearDown()
960 * @since Method available since Release 3.3.0
962 protected function backupGlobals()
964 $this->globalsBackup = array();
966 if (ini_get('register_long_arrays') == '1') {
967 $superGlobalArrays = array_merge(
968 self::$superGlobalArrays, self::$superGlobalArraysLong
971 $superGlobalArrays = self::$superGlobalArrays;
974 foreach ($superGlobalArrays as $superGlobalArray) {
975 $this->backupSuperGlobalArray($superGlobalArray);
978 foreach (array_keys($GLOBALS) as $key) {
979 if ($key != 'GLOBALS' && !in_array($key, $superGlobalArrays)) {
980 $this->globalsBackup['GLOBALS'][$key] = serialize($GLOBALS[$key]);
986 * @since Method available since Release 3.3.0
988 protected function restoreGlobals()
990 if (ini_get('register_long_arrays') == '1') {
991 $superGlobalArrays = array_merge(
992 self::$superGlobalArrays, self::$superGlobalArraysLong
995 $superGlobalArrays = self::$superGlobalArrays;
998 foreach ($superGlobalArrays as $superGlobalArray) {
999 $this->restoreSuperGlobalArray($superGlobalArray);
1002 foreach (array_keys($GLOBALS) as $key) {
1003 if ($key != 'GLOBALS' && !in_array($key, $superGlobalArrays)) {
1004 if (isset($this->globalsBackup['GLOBALS'][$key])) {
1005 $GLOBALS[$key] = unserialize($this->globalsBackup['GLOBALS'][$key]);
1007 unset($GLOBALS[$key]);
1012 $this->globalsBackup = array();
1015 protected function backupSuperGlobalArray($superGlobalArray)
1017 $this->globalsBackup[$superGlobalArray] = array();
1019 if (isset($GLOBALS[$superGlobalArray])) {
1020 foreach ($GLOBALS[$superGlobalArray] as $key => $value) {
1021 $this->globalsBackup[$superGlobalArray][$key] = serialize($value);
1026 protected function restoreSuperGlobalArray($superGlobalArray)
1028 if (isset($GLOBALS[$superGlobalArray])) {
1029 foreach ($GLOBALS[$superGlobalArray] as $key => $value) {
1030 if (isset($this->globalsBackup[$superGlobalArray][$key])) {
1031 $GLOBALS[$superGlobalArray][$key] = unserialize($this->globalsBackup[$superGlobalArray][$key]);
1033 unset($GLOBALS[$superGlobalArray][$key]);
1038 $this->globalsBackup[$superGlobalArray] = array();