<?php /** * base include file for SimpleTest * @package SimpleTest * @subpackage UnitTester * @version $Id: expectation.php 1532 2006-12-01 12:28:55Z xue $ */ /**#@+ * include other SimpleTest class files */ require_once(dirname(__FILE__) . '/dumper.php'); require_once(dirname(__FILE__) . '/compatibility.php'); /**#@-*/ /** * Assertion that can display failure information. * Also includes various helper methods. * @package SimpleTest * @subpackage UnitTester * @abstract */ class SimpleExpectation { protected $_dumper; protected $_message; /** * Creates a dumper for displaying values and sets * the test message. * @param string $message Customised message on failure. */ function SimpleExpectation($message = '%s') { $this->_dumper = new SimpleDumper(); $this->_message = $message; } /** * Tests the expectation. True if correct. * @param mixed $compare Comparison value. * @return boolean True if correct. * @access public * @abstract */ function test($compare) { } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public * @abstract */ function testMessage($compare) { } /** * Overlays the generated message onto the stored user * message. An additional message can be interjected. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function overlayMessage($compare) { return sprintf($this->_message, $this->testMessage($compare)); } /** * Accessor for the dumper. * @return SimpleDumper Current value dumper. * @access protected */ function &_getDumper() { return $this->_dumper; } /** * Test to see if a value is an expectation object. * A useful utility method. * @param mixed $expectation Hopefully an Epectation * class. * @return boolean True if descended from * this class. * @access public * @static */ static function isExpectation($expectation) { return is_object($expectation) && SimpleTestCompatibility::isA($expectation, 'SimpleExpectation'); } } /** * Test for equality. * @package SimpleTest * @subpackage UnitTester */ class EqualExpectation extends SimpleExpectation { protected $_value; /** * Sets the value to compare against. * @param mixed $value Test value to match. * @param string $message Customised message on failure. * @access public */ function EqualExpectation($value, $message = '%s') { $this->SimpleExpectation($message); $this->_value = $value; } /** * Tests the expectation. True if it matches the * held value. * @param mixed $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return (($this->_value == $compare) && ($compare == $this->_value)); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { if ($this->test($compare)) { return "Equal expectation [" . $this->_dumper->describeValue($this->_value) . "]"; } else { return "Equal expectation fails " . $this->_dumper->describeDifference($this->_value, $compare); } } /** * Accessor for comparison value. * @return mixed Held value to compare with. * @access protected */ function _getValue() { return $this->_value; } } /** * Test for inequality. * @package SimpleTest * @subpackage UnitTester */ class NotEqualExpectation extends EqualExpectation { /** * Sets the value to compare against. * @param mixed $value Test value to match. * @param string $message Customised message on failure. * @access public */ function NotEqualExpectation($value, $message = '%s') { $this->EqualExpectation($value, $message); } /** * Tests the expectation. True if it differs from the * held value. * @param mixed $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return ! parent::test($compare); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { $dumper = $this->_getDumper(); if ($this->test($compare)) { return "Not equal expectation passes " . $dumper->describeDifference($this->_getValue(), $compare); } else { return "Not equal expectation fails [" . $dumper->describeValue($this->_getValue()) . "] matches"; } } } /** * Test for being within a range. * @package SimpleTest * @subpackage UnitTester */ class WithinMarginExpectation extends SimpleExpectation { protected $_upper; protected $_lower; /** * Sets the value to compare against and the fuzziness of * the match. Used for comparing floating point values. * @param mixed $value Test value to match. * @param mixed $margin Fuzziness of match. * @param string $message Customised message on failure. * @access public */ function WithinMarginExpectation($value, $margin, $message = '%s') { $this->SimpleExpectation($message); $this->_upper = $value + $margin; $this->_lower = $value - $margin; } /** * Tests the expectation. True if it matches the * held value. * @param mixed $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return (($compare <= $this->_upper) && ($compare >= $this->_lower)); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { if ($this->test($compare)) { return $this->_withinMessage($compare); } else { return $this->_outsideMessage($compare); } } /** * Creates a the message for being within the range. * @param mixed $compare Value being tested. * @access private */ function _withinMessage($compare) { return "Within expectation [" . $this->_dumper->describeValue($this->_lower) . "] and [" . $this->_dumper->describeValue($this->_upper) . "]"; } /** * Creates a the message for being within the range. * @param mixed $compare Value being tested. * @access private */ function _outsideMessage($compare) { if ($compare > $this->_upper) { return "Outside expectation " . $this->_dumper->describeDifference($compare, $this->_upper); } else { return "Outside expectation " . $this->_dumper->describeDifference($compare, $this->_lower); } } } /** * Test for being outside of a range. * @package SimpleTest * @subpackage UnitTester */ class OutsideMarginExpectation extends WithinMarginExpectation { /** * Sets the value to compare against and the fuzziness of * the match. Used for comparing floating point values. * @param mixed $value Test value to not match. * @param mixed $margin Fuzziness of match. * @param string $message Customised message on failure. * @access public */ function OutsideMarginExpectation($value, $margin, $message = '%s') { $this->WithinMarginExpectation($value, $margin, $message); } /** * Tests the expectation. True if it matches the * held value. * @param mixed $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return ! parent::test($compare); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { if (! $this->test($compare)) { return $this->_withinMessage($compare); } else { return $this->_outsideMessage($compare); } } } /** * Test for identity. * @package SimpleTest * @subpackage UnitTester */ class IdenticalExpectation extends EqualExpectation { /** * Sets the value to compare against. * @param mixed $value Test value to match. * @param string $message Customised message on failure. * @access public */ function IdenticalExpectation($value, $message = '%s') { $this->EqualExpectation($value, $message); } /** * Tests the expectation. True if it exactly * matches the held value. * @param mixed $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return SimpleTestCompatibility::isIdentical($this->_getValue(), $compare); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { $dumper = $this->_getDumper(); if ($this->test($compare)) { return "Identical expectation [" . $dumper->describeValue($this->_getValue()) . "]"; } else { return "Identical expectation [" . $dumper->describeValue($this->_getValue()) . "] fails with [" . $dumper->describeValue($compare) . "] " . $dumper->describeDifference($this->_getValue(), $compare, TYPE_MATTERS); } } } /** * Test for non-identity. * @package SimpleTest * @subpackage UnitTester */ class NotIdenticalExpectation extends IdenticalExpectation { /** * Sets the value to compare against. * @param mixed $value Test value to match. * @param string $message Customised message on failure. * @access public */ function NotIdenticalExpectation($value, $message = '%s') { $this->IdenticalExpectation($value, $message); } /** * Tests the expectation. True if it differs from the * held value. * @param mixed $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return ! parent::test($compare); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { $dumper = $this->_getDumper(); if ($this->test($compare)) { return "Not identical expectation passes " . $dumper->describeDifference($this->_getValue(), $compare, TYPE_MATTERS); } else { return "Not identical expectation [" . $dumper->describeValue($this->_getValue()) . "] matches"; } } } /** * Test for a pattern using Perl regex rules. * @package SimpleTest * @subpackage UnitTester */ class PatternExpectation extends SimpleExpectation { protected $_pattern; /** * Sets the value to compare against. * @param string $pattern Pattern to search for. * @param string $message Customised message on failure. * @access public */ function PatternExpectation($pattern, $message = '%s') { $this->SimpleExpectation($message); $this->_pattern = $pattern; } /** * Accessor for the pattern. * @return string Perl regex as string. * @access protected */ function _getPattern() { return $this->_pattern; } /** * Tests the expectation. True if the Perl regex * matches the comparison value. * @param string $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return (boolean)preg_match($this->_getPattern(), $compare); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { if ($this->test($compare)) { return $this->_describePatternMatch($this->_getPattern(), $compare); } else { $dumper = $this->_getDumper(); return "Pattern [" . $this->_getPattern() . "] not detected in [" . $dumper->describeValue($compare) . "]"; } } /** * Describes a pattern match including the string * found and it's position. * @package SimpleTest * @subpackage UnitTester * @param string $pattern Regex to match against. * @param string $subject Subject to search. * @access protected */ function _describePatternMatch($pattern, $subject) { preg_match($pattern, $subject, $matches); $position = strpos($subject, $matches[0]); $dumper = $this->_getDumper(); return "Pattern [$pattern] detected at character [$position] in [" . $dumper->describeValue($subject) . "] as [" . $matches[0] . "] in region [" . $dumper->clipString($subject, 100, $position) . "]"; } } /** * @deprecated */ class WantedPatternExpectation extends PatternExpectation { } /** * Fail if a pattern is detected within the * comparison. * @package SimpleTest * @subpackage UnitTester */ class NoPatternExpectation extends PatternExpectation { /** * Sets the reject pattern * @param string $pattern Pattern to search for. * @param string $message Customised message on failure. * @access public */ function NoPatternExpectation($pattern, $message = '%s') { $this->PatternExpectation($pattern, $message); } /** * Tests the expectation. False if the Perl regex * matches the comparison value. * @param string $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { return ! parent::test($compare); } /** * Returns a human readable test message. * @param string $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { if ($this->test($compare)) { $dumper = $this->_getDumper(); return "Pattern [" . $this->_getPattern() . "] not detected in [" . $dumper->describeValue($compare) . "]"; } else { return $this->_describePatternMatch($this->_getPattern(), $compare); } } } /** * @package SimpleTest * @subpackage UnitTester * @deprecated */ class UnwantedPatternExpectation extends NoPatternExpectation { } /** * Tests either type or class name if it's an object. * @package SimpleTest * @subpackage UnitTester */ class IsAExpectation extends SimpleExpectation { protected $_type; /** * Sets the type to compare with. * @param string $type Type or class name. * @param string $message Customised message on failure. * @access public */ function IsAExpectation($type, $message = '%s') { $this->SimpleExpectation($message); $this->_type = $type; } /** * Accessor for type to check against. * @return string Type or class name. * @access protected */ function _getType() { return $this->_type; } /** * Tests the expectation. True if the type or * class matches the string value. * @param string $compare Comparison value. * @return boolean True if correct. * @access public */ function test($compare) { if (is_object($compare)) { return SimpleTestCompatibility::isA($compare, $this->_type); } else { return (strtolower(gettype($compare)) == $this->_canonicalType($this->_type)); } } /** * Coerces type name into a gettype() match. * @param string $type User type. * @return string Simpler type. * @access private */ function _canonicalType($type) { $type = strtolower($type); $map = array( 'bool' => 'boolean', 'float' => 'double', 'real' => 'double', 'int' => 'integer'); if (isset($map[$type])) { $type = $map[$type]; } return $type; } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { $dumper = $this->_getDumper(); return "Value [" . $dumper->describeValue($compare) . "] should be type [" . $this->_type . "]"; } } /** * Tests either type or class name if it's an object. * Will succeed if the type does not match. * @package SimpleTest * @subpackage UnitTester */ class NotAExpectation extends IsAExpectation { protected $_type; /** * Sets the type to compare with. * @param string $type Type or class name. * @param string $message Customised message on failure. * @access public */ function NotAExpectation($type, $message = '%s') { $this->IsAExpectation($type, $message); } /** * Tests the expectation. False if the type or * class matches the string value. * @param string $compare Comparison value. * @return boolean True if different. * @access public */ function test($compare) { return ! parent::test($compare); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { $dumper = $this->_getDumper(); return "Value [" . $dumper->describeValue($compare) . "] should not be type [" . $this->_getType() . "]"; } } /** * Tests for existance of a method in an object * @package SimpleTest * @subpackage UnitTester */ class MethodExistsExpectation extends SimpleExpectation { protected $_method; /** * Sets the value to compare against. * @param string $method Method to check. * @param string $message Customised message on failure. * @access public * @return void */ function MethodExistsExpectation($method, $message = '%s') { $this->SimpleExpectation($message); $this->_method = $method; } /** * Tests the expectation. True if the method exists in the test object. * @param string $compare Comparison method name. * @return boolean True if correct. * @access public */ function test($compare) { return (boolean)(is_object($compare) && method_exists($compare, $this->_method)); } /** * Returns a human readable test message. * @param mixed $compare Comparison value. * @return string Description of success * or failure. * @access public */ function testMessage($compare) { $dumper = $this->_getDumper(); if (! is_object($compare)) { return 'No method on non-object [' . $dumper->describeValue($compare) . ']'; } $method = $this->_method; return "Object [" . $dumper->describeValue($compare) . "] should contain method [$method]"; } }