mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2025-01-18 18:46:17 +00:00
da79dff7d7
- Dispatcher sets a Controller::here variable with the real URL used to access the page, so that tag generators can that use an url (linkTo and formTag for example) use the real url, not guess it from the controller and action names which often fails - Log class works more reliably and a LogError() shortcut function was added - Nstring class added, to store string-related functions (there are just four yet, including a random password generator and an string-to-array splitter - SimpleTest library (with Rephlux) included in /vendors; I've tweaked SimpleScorer::inCli() function, because it didn't work on my setup, it should work everywhere now (it checks for empty REQUEST_METHOD, which should only be empty in CLI) git-svn-id: https://svn.cakephp.org/repo/trunk/cake@248 3807eeeb-6ff5-0310-8944-8be069107fe0
553 lines
19 KiB
PHP
553 lines
19 KiB
PHP
<?php
|
|
/**
|
|
* Base include file for SimpleTest
|
|
* @package SimpleTest
|
|
* @subpackage UnitTester
|
|
* @version $Id$
|
|
*/
|
|
|
|
/**#@+
|
|
* 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 {
|
|
var $_label;
|
|
var $_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 {
|
|
var $_label;
|
|
var $_test_cases;
|
|
var $_old_track_errors;
|
|
var $_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 {
|
|
var $_label;
|
|
var $_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;
|
|
}
|
|
}
|
|
?>
|