| <?php |
| /** |
| * PHPUnit |
| * |
| * Copyright (c) 2002-2008, Sebastian Bergmann <sb@sebastian-bergmann.de>. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * * Neither the name of Sebastian Bergmann nor the names of his |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
| * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
| * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
| * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| * |
| * @category Testing |
| * @package PHPUnit |
| * @author Sebastian Bergmann <sb@sebastian-bergmann.de> |
| * @copyright 2002-2008 Sebastian Bergmann <sb@sebastian-bergmann.de> |
| * @license http://www.opensource.org/licenses/bsd-license.php BSD License |
| * @version SVN: $Id: TestCase.php 2135 2008-01-17 10:45:15Z sb $ |
| * @link http://www.phpunit.de/ |
| * @since File available since Release 2.0.0 |
| */ |
| |
| require_once 'PHPUnit/Framework.php'; |
| require_once 'PHPUnit/Framework/MockObject/Mock.php'; |
| require_once 'PHPUnit/Framework/MockObject/Matcher/InvokedAtLeastOnce.php'; |
| require_once 'PHPUnit/Framework/MockObject/Matcher/InvokedAtIndex.php'; |
| require_once 'PHPUnit/Framework/MockObject/Matcher/InvokedCount.php'; |
| require_once 'PHPUnit/Framework/MockObject/Stub.php'; |
| require_once 'PHPUnit/Runner/BaseTestRunner.php'; |
| require_once 'PHPUnit/Util/Filter.php'; |
| |
| PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT'); |
| |
| if (! class_exists('PHPUnit_Framework_TestCase', FALSE)) { |
| |
| /** |
| * A TestCase defines the fixture to run multiple tests. |
| * |
| * To define a TestCase |
| * |
| * 1) Implement a subclass of PHPUnit_Framework_TestCase. |
| * 2) Define instance variables that store the state of the fixture. |
| * 3) Initialize the fixture state by overriding setUp(). |
| * 4) Clean-up after a test by overriding tearDown(). |
| * |
| * Each test runs in its own fixture so there can be no side effects |
| * among test runs. |
| * |
| * Here is an example: |
| * |
| * <code> |
| * <?php |
| * require_once 'PHPUnit/Framework/TestCase.php'; |
| * |
| * class MathTest extends PHPUnit_Framework_TestCase |
| * { |
| * public $value1; |
| * public $value2; |
| * |
| * protected function setUp() |
| * { |
| * $this->value1 = 2; |
| * $this->value2 = 3; |
| * } |
| * } |
| * ?> |
| * </code> |
| * |
| * For each test implement a method which interacts with the fixture. |
| * Verify the expected results with assertions specified by calling |
| * assert with a boolean. |
| * |
| * <code> |
| * <?php |
| * public function testPass() |
| * { |
| * $this->assertTrue($this->value1 + $this->value2 == 5); |
| * } |
| * ?> |
| * </code> |
| * |
| * @category Testing |
| * @package PHPUnit |
| * @author Sebastian Bergmann <sb@sebastian-bergmann.de> |
| * @copyright 2002-2008 Sebastian Bergmann <sb@sebastian-bergmann.de> |
| * @license http://www.opensource.org/licenses/bsd-license.php BSD License |
| * @version Release: 3.2.9 |
| * @link http://www.phpunit.de/ |
| * @since Class available since Release 2.0.0 |
| * @abstract |
| */ |
| abstract class PHPUnit_Framework_TestCase extends PHPUnit_Framework_Assert implements PHPUnit_Framework_Test, PHPUnit_Framework_SelfDescribing { |
| /** |
| * Enable or disable the backup and restoration of the $GLOBALS array. |
| * Overwrite this attribute in a child class of TestCase. |
| * Setting this attribute in setUp() has no effect! |
| * |
| * @var boolean |
| * @access protected |
| */ |
| protected $backupGlobals = TRUE; |
| |
| /** |
| * Enable or disable creating the $GLOBALS reference that is required |
| * for the "global" keyword to work correctly. |
| * Overwrite this attribute in a child class of TestCase. |
| * Setting this attribute in setUp() has no effect! |
| * |
| * @var boolean |
| * @access protected |
| */ |
| protected $createGlobalsReference = FALSE; |
| |
| /** |
| * @var array |
| * @access protected |
| */ |
| protected $data = array(); |
| |
| /** |
| * @var string |
| * @access protected |
| */ |
| protected $dataName = ''; |
| |
| /** |
| * The name of the expected Exception. |
| * |
| * @var mixed |
| * @access protected |
| */ |
| protected $expectedException = NULL; |
| |
| /** |
| * The message of the expected Exception. |
| * |
| * @var string |
| * @access protected |
| */ |
| protected $expectedExceptionMessage = ''; |
| |
| /** |
| * Fixture that is shared between the tests of a test suite. |
| * |
| * @var mixed |
| * @access protected |
| */ |
| protected $sharedFixture; |
| |
| /** |
| * The name of the test case. |
| * |
| * @var string |
| * @access protected |
| */ |
| protected $name = NULL; |
| |
| /** |
| * @var Exception |
| * @access protected |
| */ |
| protected $exception = NULL; |
| |
| /** |
| * @var string |
| * @access protected |
| */ |
| protected $exceptionMessage = NULL; |
| |
| /** |
| * @var integer |
| * @access protected |
| */ |
| protected $exceptionCode = 0; |
| |
| /** |
| * @var Array |
| * @access protected |
| */ |
| protected $iniSettings = array(); |
| |
| /** |
| * @var Array |
| * @access protected |
| */ |
| protected $locale = array(); |
| |
| /** |
| * @var Array |
| * @access protected |
| */ |
| protected $mockObjects = array(); |
| |
| /** |
| * Constructs a test case with the given name. |
| * |
| * @param string $name |
| * @param array $data |
| * @param string $dataName |
| * @access public |
| */ |
| public function __construct($name = NULL, array $data = array(), $dataName = '') { |
| if ($name !== NULL) { |
| $this->setName($name); |
| } |
| |
| $this->data = $data; |
| $this->dataName = $dataName; |
| } |
| |
| /** |
| * Returns a string representation of the test case. |
| * |
| * @return string |
| * @access public |
| */ |
| public function toString() { |
| $class = new ReflectionClass($this); |
| |
| $buffer = sprintf('%s(%s)', |
| |
| $this->getName(), $class->name); |
| |
| if (! empty($this->data)) { |
| if (is_string($this->dataName)) { |
| $buffer .= sprintf(' with data set "%s"', |
| |
| $this->dataName); |
| } else { |
| $buffer .= sprintf(' with data set #%d (%s)', |
| |
| $this->dataName, $this->dataToString($this->data)); |
| } |
| } |
| |
| return $buffer; |
| } |
| |
| /** |
| * Counts the number of test cases executed by run(TestResult result). |
| * |
| * @return integer |
| * @access public |
| */ |
| public function count() { |
| return 1; |
| } |
| |
| /** |
| * Gets the name of a TestCase. |
| * |
| * @return string |
| * @access public |
| */ |
| public function getName() { |
| return $this->name; |
| } |
| |
| /** |
| * @return string |
| * @access public |
| * @since Method available since Release 3.2.0 |
| */ |
| public function getExpectedException() { |
| return $this->expectedException; |
| } |
| |
| /** |
| * @param mixed $exceptionName |
| * @param string $exceptionMessage |
| * @param integer $exceptionCode |
| * @access public |
| * @since Method available since Release 3.2.0 |
| */ |
| public function setExpectedException($exceptionName, $exceptionMessage = '', $exceptionCode = 0) { |
| $this->expectedException = $exceptionName; |
| $this->expectedExceptionMessage = $exceptionMessage; |
| $this->expectedExceptionCode = $exceptionCode; |
| } |
| |
| /** |
| * Returns the status of this test. |
| * |
| * @return integer |
| * @since Method available since Release 3.1.0 |
| */ |
| public function getStatus() { |
| if ($this->exception === NULL) { |
| return PHPUnit_Runner_BaseTestRunner::STATUS_PASSED; |
| } |
| |
| if ($this->exception instanceof PHPUnit_Framework_IncompleteTest) { |
| return PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE; |
| } |
| |
| if ($this->exception instanceof PHPUnit_Framework_SkippedTest) { |
| return PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED; |
| } |
| |
| if ($this->exception instanceof PHPUnit_Framework_AssertionFailedError) { |
| return PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE; |
| } |
| |
| return PHPUnit_Runner_BaseTestRunner::STATUS_ERROR; |
| } |
| |
| /** |
| * Returns whether or not this test has failed. |
| * |
| * @return boolean |
| * @since Method available since Release 3.0.0 |
| */ |
| public function hasFailed() { |
| $status = $this->getStatus(); |
| |
| return $status == PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE || $status == PHPUnit_Runner_BaseTestRunner::STATUS_ERROR; |
| } |
| |
| /** |
| * Runs the test case and collects the results in a TestResult object. |
| * If no TestResult object is passed a new one will be created. |
| * |
| * @param PHPUnit_Framework_TestResult $result |
| * @return PHPUnit_Framework_TestResult |
| * @throws InvalidArgumentException |
| * @access public |
| */ |
| public function run(PHPUnit_Framework_TestResult $result = NULL) { |
| if ($result === NULL) { |
| $result = $this->createResult(); |
| } |
| |
| $result->run($this); |
| |
| return $result; |
| } |
| |
| /** |
| * Runs the bare test sequence. |
| * |
| * @access public |
| */ |
| public function runBare() { |
| // Backup the $GLOBALS array. |
| if ($this->backupGlobals === TRUE) { |
| $globalsBackup = serialize($GLOBALS); |
| } |
| |
| // Set up the fixture. |
| $this->setUp(); |
| |
| // Run the test. |
| try { |
| // Assert pre-conditions. |
| $this->assertPreConditions(); |
| |
| $this->runTest(); |
| |
| // Assert post-conditions. |
| $this->assertPostConditions(); |
| |
| // Verify Mock Object conditions. |
| foreach ($this->mockObjects as $mockObject) { |
| $mockObject->verify(); |
| } |
| |
| $this->mockObjects = array(); |
| } |
| |
| catch (Exception $e) { |
| $this->exception = $e; |
| } |
| |
| // Tear down the fixture. |
| $this->tearDown(); |
| |
| // Restore the $GLOBALS array. |
| if ($this->backupGlobals === TRUE) { |
| $GLOBALS = unserialize($globalsBackup); |
| |
| if ($this->createGlobalsReference) { |
| $GLOBALS['GLOBALS'] = &$GLOBALS; |
| } |
| } |
| |
| // Clean up INI settings. |
| foreach ($this->iniSettings as $varName => $oldValue) { |
| ini_set($varName, $oldValue); |
| } |
| |
| $this->iniSettings = array(); |
| |
| // Clean up locale settings. |
| foreach ($this->locale as $category => $locale) { |
| setlocale($category, $locale); |
| } |
| |
| // Clean up stat cache. |
| clearstatcache(); |
| |
| // Workaround for missing "finally". |
| if ($this->exception !== NULL) { |
| throw $this->exception; |
| } |
| } |
| |
| /** |
| * Override to run the test and assert its state. |
| * |
| * @throws RuntimeException |
| * @access protected |
| */ |
| protected function runTest() { |
| if ($this->name === NULL) { |
| throw new RuntimeException('PHPUnit_Framework_TestCase::$name must not be NULL.'); |
| } |
| |
| try { |
| $class = new ReflectionClass($this); |
| $method = $class->getMethod($this->name); |
| } |
| |
| catch (ReflectionException $e) { |
| $this->fail($e->getMessage()); |
| } |
| |
| try { |
| if (empty($this->data)) { |
| $method->invoke($this); |
| } else { |
| $method->invokeArgs($this, $this->data); |
| } |
| } |
| |
| catch (Exception $e) { |
| if (is_string($this->expectedException) && $e instanceof $this->expectedException) { |
| if (is_string($this->expectedExceptionMessage) && ! empty($this->expectedExceptionMessage)) { |
| $this->assertContains($this->expectedExceptionMessage, $e->getMessage()); |
| } |
| |
| if (is_int($this->expectedExceptionCode) && $this->expectedExceptionCode !== 0) { |
| $this->assertEquals($this->expectedExceptionCode, $e->getCode()); |
| } |
| |
| return; |
| } else { |
| throw $e; |
| } |
| } |
| |
| if ($this->expectedException !== NULL) { |
| $this->fail('Expected exception ' . $this->expectedException); |
| } |
| } |
| |
| /** |
| * Sets the name of a TestCase. |
| * |
| * @param string |
| * @access public |
| */ |
| public function setName($name) { |
| $this->name = $name; |
| } |
| |
| /** |
| * Sets the shared fixture. |
| * |
| * @param mixed $sharedFixture |
| * @access public |
| * @since Method available since Release 3.1.0 |
| */ |
| public function setSharedFixture($sharedFixture) { |
| $this->sharedFixture = $sharedFixture; |
| } |
| |
| /** |
| * This method is a wrapper for the ini_set() function that automatically |
| * resets the modified php.ini setting to its original value after the |
| * test is run. |
| * |
| * @param string $varName |
| * @param string $newValue |
| * @throws InvalidArgumentException |
| * @throws RuntimeException |
| * @access protected |
| * @since Method available since Release 3.0.0 |
| */ |
| protected function iniSet($varName, $newValue) { |
| if (! is_string($varName) || ! is_string($newValue)) { |
| throw new InvalidArgumentException(); |
| } |
| |
| $currentValue = ini_set($varName, $newValue); |
| |
| if ($currentValue !== FALSE) { |
| $this->iniSettings[$varName] = $currentValue; |
| } else { |
| throw new RuntimeException(); |
| } |
| } |
| |
| /** |
| * This method is a wrapper for the setlocale() function that automatically |
| * resets the locale to its original value after the test is run. |
| * |
| * @param integer $category |
| * @param string $locale |
| * @throws InvalidArgumentException |
| * @throws RuntimeException |
| * @access protected |
| * @since Method available since Release 3.1.0 |
| */ |
| protected function setLocale() { |
| $args = func_get_args(); |
| |
| if (count($args) < 2) { |
| throw new InvalidArgumentException(); |
| } |
| |
| $category = $args[0]; |
| $locale = $args[1]; |
| |
| if (! in_array($category, array(LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, |
| LC_TIME, LC_MESSAGES))) { |
| throw new InvalidArgumentException(); |
| } |
| |
| if (! is_array($locale) && ! is_string($locale)) { |
| throw new InvalidArgumentException(); |
| } |
| |
| $this->locale[$category] = setlocale($category, NULL); |
| |
| $result = call_user_func_array('setlocale', $args); |
| |
| if ($result === FALSE) { |
| throw new RuntimeException('The locale functionality is not implemented on your platform, ' . 'the specified locale does not exist or the category name is ' . 'invalid.'); |
| } |
| } |
| |
| /** |
| * Returns a mock object for the specified class. |
| * |
| * @param string $className |
| * @param array $methods |
| * @param array $arguments |
| * @param string $mockClassName |
| * @param boolean $callOriginalConstructor |
| * @param boolean $callOriginalClone |
| * @param boolean $callAutoload |
| * @return object |
| * @access protected |
| * @since Method available since Release 3.0.0 |
| */ |
| protected function getMock($className, array $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE) { |
| if (! is_string($className) || ! is_string($mockClassName)) { |
| throw new InvalidArgumentException(); |
| } |
| |
| $mock = PHPUnit_Framework_MockObject_Mock::generate($className, $methods, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload); |
| |
| $mockClass = new ReflectionClass($mock->mockClassName); |
| $mockObject = $mockClass->newInstanceArgs($arguments); |
| |
| $this->mockObjects[] = $mockObject; |
| |
| return $mockObject; |
| } |
| |
| /** |
| * Returns a matcher that matches when the method it is evaluated for |
| * is executed zero or more times. |
| * |
| * @return PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount |
| * @access protected |
| * @since Method available since Release 3.0.0 |
| */ |
| protected function any() { |
| return new PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount(); |
| } |
| |
| /** |
| * Returns a matcher that matches when the method it is evaluated for |
| * is never executed. |
| * |
| * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount |
| * @access protected |
| * @since Method available since Release 3.0.0 |
| */ |
| protected function never() { |
| return new PHPUnit_Framework_MockObject_Matcher_InvokedCount(0); |
| } |
| |
| /** |
| * Returns a matcher that matches when the method it is evaluated for |
| * is executed at least once. |
| * |
| * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce |
| * @access protected |
| * @since Method available since Release 3.0.0 |
| */ |
| protected function atLeastOnce() { |
| return new PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce(); |
| } |
| |
| /** |
| * Returns a matcher that matches when the method it is evaluated for |
| * is executed exactly once. |
| * |
| * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount |
| * @access protected |
| * @since Method available since Release 3.0.0 |
| */ |
| protected function once() { |
| return new PHPUnit_Framework_MockObject_Matcher_InvokedCount(1); |
| } |
| |
| /** |
| * Returns a matcher that matches when the method it is evaluated for |
| * is executed exactly $count times. |
| * |
| * @param integer $count |
| * @return PHPUnit_Framework_MockObject_Matcher_InvokedCount |
| * @access protected |
| * @since Method available since Release 3.0.0 |
| */ |
| protected function exactly($count) { |
| return new PHPUnit_Framework_MockObject_Matcher_InvokedCount($count); |
| } |
| |
| /** |
| * Returns a matcher that matches when the method it is evaluated for |
| * is invoked at the given $index. |
| * |
| * @param integer $index |
| * @return PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex |
| * @access protected |
| * @since Method available since Release 3.0.0 |
| */ |
| protected function at($index) { |
| return new PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex($index); |
| } |
| |
| /** |
| * |
| * |
| * @param mixed $value |
| * @return PHPUnit_Framework_MockObject_Stub_Return |
| * @access protected |
| * @since Method available since Release 3.0.0 |
| */ |
| protected function returnValue($value) { |
| return new PHPUnit_Framework_MockObject_Stub_Return($value); |
| } |
| |
| /** |
| * |
| * |
| * @param Exception $exception |
| * @return PHPUnit_Framework_MockObject_Stub_Exception |
| * @access protected |
| * @since Method available since Release 3.1.0 |
| */ |
| protected function throwException(Exception $exception) { |
| return new PHPUnit_Framework_MockObject_Stub_Exception($exception); |
| } |
| |
| /** |
| * |
| * |
| * @param mixed $value, ... |
| * @return PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls |
| * @access protected |
| * @since Method available since Release 3.0.0 |
| */ |
| protected function onConsecutiveCalls() { |
| $args = func_get_args(); |
| |
| return new PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls($args); |
| } |
| |
| /** |
| * @param mixed $data |
| * @return string |
| * @access protected |
| * @since Method available since Release 3.2.1 |
| */ |
| protected function dataToString($data) { |
| $result = array(); |
| |
| foreach ($data as $_data) { |
| if (is_array($_data)) { |
| $result[] = 'array(' . $this->dataToString($_data) . ')'; |
| } |
| |
| else if (is_object($_data)) { |
| $object = new ReflectionObject($_data); |
| |
| if ($object->hasMethod('__toString')) { |
| $result[] = (string)$_data; |
| } else { |
| $result[] = get_class($_data); |
| } |
| } |
| |
| else if (is_resource($_data)) { |
| $result[] = '<resource>'; |
| } |
| |
| else { |
| $result[] = var_export($_data, TRUE); |
| } |
| } |
| |
| return join(', ', $result); |
| } |
| |
| /** |
| * Creates a default TestResult object. |
| * |
| * @return PHPUnit_Framework_TestResult |
| * @access protected |
| */ |
| protected function createResult() { |
| return new PHPUnit_Framework_TestResult(); |
| } |
| |
| /** |
| * Sets up the fixture, for example, open a network connection. |
| * This method is called before a test is executed. |
| * |
| * @access protected |
| */ |
| protected function setUp() {} |
| |
| /** |
| * Performs assertions shared by all tests of a test case. |
| * |
| * This method is called before the execution of a test starts |
| * and after setUp() is called. |
| * |
| * @access protected |
| * @since Method available since Release 3.2.8 |
| */ |
| protected function assertPreConditions() {} |
| |
| /** |
| * Performs assertions shared by all tests of a test case. |
| * |
| * This method is called before the execution of a test ends |
| * and before tearDown() is called. |
| * |
| * @access protected |
| * @since Method available since Release 3.2.8 |
| */ |
| protected function assertPostConditions() { |
| // assertPostConditions() was named sharedAssertions() in |
| // PHPUnit 3.0.0-3.2.7. |
| if (method_exists($this, 'sharedAssertions')) { |
| $this->sharedAssertions(); |
| } |
| } |
| |
| /** |
| * Tears down the fixture, for example, close a network connection. |
| * This method is called after a test is executed. |
| * |
| * @access protected |
| */ |
| protected function tearDown() {} |
| } |
| |
| } |
| ?> |