diff options
author | xue <> | 2006-07-07 14:54:15 +0000 |
---|---|---|
committer | xue <> | 2006-07-07 14:54:15 +0000 |
commit | 61bb16ee2e5f0a66234e1575242169a10fde47b5 (patch) | |
tree | 3ee24dcc36ceae2c213130df1ea3d5c9fc110a27 /tests/test_tools/simpletest/simple_test.php | |
parent | 7b84938b1b5964f2274d66e28ba17435924ffe35 (diff) |
Merge from 3.0 branch till 1253.
Diffstat (limited to 'tests/test_tools/simpletest/simple_test.php')
-rw-r--r-- | tests/test_tools/simpletest/simple_test.php | 553 |
1 files changed, 553 insertions, 0 deletions
diff --git a/tests/test_tools/simpletest/simple_test.php b/tests/test_tools/simpletest/simple_test.php new file mode 100644 index 00000000..f2204f42 --- /dev/null +++ b/tests/test_tools/simpletest/simple_test.php @@ -0,0 +1,553 @@ +<?php + /** + * Base include file for SimpleTest + * @package SimpleTest + * @subpackage UnitTester + * @version $Id: simple_test.php,v 1.89 2005/02/18 19:25:05 lastcraft Exp $ + */ + + /**#@+ + * Includes SimpleTest files and defined the root constant + * for dependent libraries. + */ + require_once(dirname(__FILE__) . '/errors.php'); + require_once(dirname(__FILE__) . '/options.php'); + require_once(dirname(__FILE__) . '/runner.php'); + require_once(dirname(__FILE__) . '/scorer.php'); + require_once(dirname(__FILE__) . '/expectation.php'); + require_once(dirname(__FILE__) . '/dumper.php'); + if (! defined('SIMPLE_TEST')) { + define('SIMPLE_TEST', dirname(__FILE__) . '/'); + } + /**#@-*/ + + /** + * Basic test case. This is the smallest unit of a test + * suite. It searches for + * all methods that start with the the string "test" and + * runs them. Working test cases extend this class. + * @package SimpleTest + * @subpackage UnitTester + */ + class SimpleTestCase { + protected $_label; + protected $_runner; + + /** + * Sets up the test with no display. + * @param string $label If no test name is given then + * the class name is used. + * @access public + */ + function SimpleTestCase($label = false) { + $this->_label = $label ? $label : get_class($this); + $this->_runner = false; + } + + /** + * Accessor for the test name for subclasses. + * @return string Name of the test. + * @access public + */ + function getLabel() { + return $this->_label; + } + + /** + * Used to invoke the single tests. + * @return SimpleInvoker Individual test runner. + * @access public + */ + function createInvoker() { + return new SimpleErrorTrappingInvoker(new SimpleInvoker($this)); + } + + /** + * Can modify the incoming reporter so as to run + * the tests differently. This version simply + * passes it straight through. + * @param SimpleReporter $reporter Incoming observer. + * @return SimpleReporter + * @access protected + */ + function _createRunner($reporter) { + return new SimpleRunner($this, $reporter); + } + + /** + * Uses reflection to run every method within itself + * starting with the string "test" unless a method + * is specified. + * @param SimpleReporter $reporter Current test reporter. + * @access public + */ + function run($reporter) { + $reporter->paintCaseStart($this->getLabel()); + $this->_runner = $this->_createRunner($reporter); + $this->_runner->run(); + $reporter->paintCaseEnd($this->getLabel()); + return $reporter->getStatus(); + } + + /** + * Sets up unit test wide variables at the start + * of each test method. To be overridden in + * actual user test cases. + * @access public + */ + function setUp() { + } + + /** + * Clears the data set in the setUp() method call. + * To be overridden by the user in actual user test cases. + * @access public + */ + function tearDown() { + } + + /** + * Sends a pass event with a message. + * @param string $message Message to send. + * @access public + */ + function pass($message = "Pass") { + $this->_runner->paintPass($message . $this->getAssertionLine(' at line [%d]')); + } + + /** + * Sends a fail event with a message. + * @param string $message Message to send. + * @access public + */ + function fail($message = "Fail") { + $this->_runner->paintFail($message . $this->getAssertionLine(' at line [%d]')); + } + + /** + * Formats a PHP error and dispatches it to the + * runner. + * @param integer $severity PHP error code. + * @param string $message Text of error. + * @param string $file File error occoured in. + * @param integer $line Line number of error. + * @param hash $globals PHP super global arrays. + * @access public + */ + function error($severity, $message, $file, $line, $globals) { + $severity = SimpleErrorQueue::getSeverityAsString($severity); + $this->_runner->paintError( + "Unexpected PHP error [$message] severity [$severity] in [$file] line [$line]"); + } + + /** + * Sends a user defined event to the test runner. + * This is for small scale extension where + * both the test case and either the runner or + * display are subclassed. + * @param string $type Type of event. + * @param mixed $payload Object or message to deliver. + * @access public + */ + function signal($type, $payload) { + $this->_runner->paintSignal($type, $payload); + } + + /** + * Cancels any outstanding errors. + * @access public + */ + function swallowErrors() { + $queue = SimpleErrorQueue::instance(); + $queue->clear(); + } + + /** + * Runs an expectation directly, for extending the + * tests with new expectation classes. + * @param SimpleExpectation $expectation Expectation subclass. + * @param mixed $test_value Value to compare. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertExpectation($expectation, $test_value, $message = '%s') { + return $this->assertTrue( + $expectation->test($test_value), + sprintf($message, $expectation->overlayMessage($test_value))); + } + + /** + * Called from within the test methods to register + * passes and failures. + * @param boolean $result Pass on true. + * @param string $message Message to display describing + * the test state. + * @return boolean True on pass + * @access public + */ + function assertTrue($result, $message = false) { + if (! $message) { + $message = 'True assertion got ' . ($result ? 'True' : 'False'); + } + if ($result) { + $this->pass($message); + return true; + } else { + $this->fail($message); + return false; + } + } + + /** + * Will be true on false and vice versa. False + * is the PHP definition of false, so that null, + * empty strings, zero and an empty array all count + * as false. + * @param boolean $result Pass on false. + * @param string $message Message to display. + * @return boolean True on pass + * @access public + */ + function assertFalse($result, $message = false) { + if (! $message) { + $message = 'False assertion got ' . ($result ? 'True' : 'False'); + } + return $this->assertTrue(! $result, $message); + } + + /** + * Uses a stack trace to find the line of an assertion. + * @param string $format String formatting. + * @param array $stack Stack frames top most first. Only + * needed if not using the PHP + * backtrace function. + * @return string Line number of first assert* + * method embedded in format string. + * @access public + */ + function getAssertionLine($format = '%d', $stack = false) { + if ($stack === false) { + $stack = SimpleTestCompatibility::getStackTrace(); + } + return SimpleDumper::getFormattedAssertionLine($stack, $format); + } + + /** + * Sends a formatted dump of a variable to the + * test suite for those emergency debugging + * situations. + * @param mixed $variable Variable to display. + * @param string $message Message to display. + * @return mixed The original variable. + * @access public + */ + function dump($variable, $message = false) { + $formatted = SimpleDumper::dump($variable); + if ($message) { + $formatted = $message . "\n" . $formatted; + } + $this->_runner->paintFormattedMessage($formatted); + return $variable; + } + + /** + * Dispatches a text message straight to the + * test suite. Useful for status bar displays. + * @param string $message Message to show. + * @access public + */ + function sendMessage($message) { + $this->_runner->PaintMessage($message); + } + + /** + * Accessor for the number of subtests. + * @return integer Number of test cases. + * @access public + * @static + */ + function getSize() { + return 1; + } + } + + /** + * This is a composite test class for combining + * test cases and other RunnableTest classes into + * a group test. + * @package SimpleTest + * @subpackage UnitTester + */ + class GroupTest { + protected $_label; + protected $_test_cases; + protected $_old_track_errors; + protected $_xdebug_is_enabled; + + /** + * Sets the name of the test suite. + * @param string $label Name sent at the start and end + * of the test. + * @access public + */ + function GroupTest($label) { + $this->_label = $label; + $this->_test_cases = array(); + $this->_old_track_errors = ini_get('track_errors'); + $this->_xdebug_is_enabled = function_exists('xdebug_is_enabled') ? + xdebug_is_enabled() : false; + } + + /** + * Accessor for the test name for subclasses. + * @return string Name of the test. + * @access public + */ + function getLabel() { + return $this->_label; + } + + /** + * Adds a test into the suite. Can be either a group + * test or some other unit test. + * @param SimpleTestCase $test_case Suite or individual test + * case implementing the + * runnable test interface. + * @access public + */ + function addTestCase($test_case) { + $this->_test_cases[] = $test_case; + } + + /** + * Adds a test into the suite by class name. The class will + * be instantiated as needed. + * @param SimpleTestCase $test_case Suite or individual test + * case implementing the + * runnable test interface. + * @access public + */ + function addTestClass($class) { + $this->_test_cases[] = $class; + } + + /** + * Builds a group test from a library of test cases. + * The new group is composed into this one. + * @param string $test_file File name of library with + * test case classes. + * @access public + */ + function addTestFile($test_file) { + $existing_classes = get_declared_classes(); + if ($error = $this->_requireWithError($test_file)) { + $this->addTestCase(new BadGroupTest($test_file, $error)); + return; + } + $classes = $this->_selectRunnableTests($existing_classes, get_declared_classes()); + if (count($classes) == 0) { + $this->addTestCase(new BadGroupTest($test_file, 'No new test cases')); + return; + } + $this->addTestCase($this->_createGroupFromClasses($test_file, $classes)); + } + + /** + * Requires a source file recording any syntax errors. + * @param string $file File name to require in. + * @return string/boolean An error message on failure or false + * if no errors. + * @access private + */ + function _requireWithError($file) { + $this->_enableErrorReporting(); + include($file); + $error = isset($php_errormsg) ? $php_errormsg : false; + $this->_disableErrorReporting(); + $self_inflicted = array( + 'Assigning the return value of new by reference is deprecated', + 'var: Deprecated. Please use the public/private/protected modifiers'); + if (in_array($error, $self_inflicted)) { + return false; + } + return $error; + } + + /** + * Sets up detection of parse errors. Note that XDebug + * interferes with this and has to be disabled. This is + * to make sure the correct error code is returned + * from unattended scripts. + * @access private + */ + function _enableErrorReporting() { + if ($this->_xdebug_is_enabled) { + xdebug_disable(); + } + ini_set('track_errors', true); + } + + /** + * Resets detection of parse errors to their old values. + * This is to make sure the correct error code is returned + * from unattended scripts. + * @access private + */ + function _disableErrorReporting() { + ini_set('track_errors', $this->_old_track_errors); + if ($this->_xdebug_is_enabled) { + xdebug_enable(); + } + } + + /** + * Calculates the incoming test cases from a before + * and after list of loaded classes. + * @param array $existing_classes Classes before require(). + * @param array $new_classes Classes after require(). + * @return array New classes which are test + * cases that shouldn't be ignored. + * @access private + */ + function _selectRunnableTests($existing_classes, $new_classes) { + $classes = array(); + foreach ($new_classes as $class) { + if (in_array($class, $existing_classes)) { + continue; + } + if (! $this->_isTestCase($class)) { + continue; + } + $classes[] = $class; + } + return $classes; + } + + /** + * Builds a group test from a class list. + * @param string $title Title of new group. + * @param array $classes Test classes. + * @return GroupTest Group loaded with the new + * test cases. + * @access private + */ + function _createGroupFromClasses($title, $classes) { + $group = new GroupTest($title); + foreach ($classes as $class) { + if (SimpleTestOptions::isIgnored($class)) { + continue; + } + $group->addTestClass($class); + } + return $group; + } + + /** + * Test to see if a class is derived from the + * TestCase class. + * @param string $class Class name. + * @access private + */ + function _isTestCase($class) { + while ($class = get_parent_class($class)) { + $class = strtolower($class); + if ($class == "simpletestcase" || $class == "grouptest") { + return true; + } + } + return false; + } + + /** + * Invokes run() on all of the held test cases, instantiating + * them if necessary. + * @param SimpleReporter $reporter Current test reporter. + * @access public + */ + function run($reporter) { + $reporter->paintGroupStart($this->getLabel(), $this->getSize()); + for ($i = 0, $count = count($this->_test_cases); $i < $count; $i++) { + if (is_string($this->_test_cases[$i])) { + $class = $this->_test_cases[$i]; + $test = new $class(); + $test->run($reporter); + } else { + $this->_test_cases[$i]->run($reporter); + } + } + $reporter->paintGroupEnd($this->getLabel()); + return $reporter->getStatus(); + } + + /** + * Number of contained test cases. + * @return integer Total count of cases in the group. + * @access public + */ + function getSize() { + $count = 0; + foreach ($this->_test_cases as $case) { + if (is_string($case)) { + $count++; + } else { + $count += $case->getSize(); + } + } + return $count; + } + } + + /** + * This is a failing group test for when a test suite hasn't + * loaded properly. + * @package SimpleTest + * @subpackage UnitTester + */ + class BadGroupTest { + protected $_label; + protected $_error; + + /** + * Sets the name of the test suite and error message. + * @param string $label Name sent at the start and end + * of the test. + * @access public + */ + function BadGroupTest($label, $error) { + $this->_label = $label; + $this->_error = $error; + } + + /** + * Accessor for the test name for subclasses. + * @return string Name of the test. + * @access public + */ + function getLabel() { + return $this->_label; + } + + /** + * Sends a single error to the reporter. + * @param SimpleReporter $reporter Current test reporter. + * @access public + */ + function run($reporter) { + $reporter->paintGroupStart($this->getLabel(), $this->getSize()); + $reporter->paintFail('Bad GroupTest [' . $this->getLabel() . + '] with error [' . $this->_error . ']'); + $reporter->paintGroupEnd($this->getLabel()); + return $reporter->getStatus(); + } + + /** + * Number of contained test cases. Always zero. + * @return integer Total count of cases in the group. + * @access public + */ + function getSize() { + return 0; + } + } +?> |