From 504c97925cf928f38c47ef6ce02b3c9ce8d5a53e Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Fri, 6 Mar 2015 10:32:26 +0800 Subject: [PATCH] MDL-47449 phpunit: Add comparitor for isEqual with exceptions We often do isEqual tests but where a field, may have a single exception. Ordinarily we can handle this easily by breaking the test down, but when dealing with mocked objects we can only pass an instance of a PHPUnit_Framework_Constraint, or a single value (which is cast to an instance of PHPUnit_Framework_Constraint_IsEqual). To deal with instances of time-based exception, we need to be able to compare simple objects and classes where one or two values may be different. --- ...traint_object_is_equal_with_exceptions.php | 86 +++++++++++++++++++ lib/phpunit/lib.php | 1 + 2 files changed, 87 insertions(+) create mode 100644 lib/phpunit/classes/constraint_object_is_equal_with_exceptions.php diff --git a/lib/phpunit/classes/constraint_object_is_equal_with_exceptions.php b/lib/phpunit/classes/constraint_object_is_equal_with_exceptions.php new file mode 100644 index 0000000000000..fc5ac7a8a64db --- /dev/null +++ b/lib/phpunit/classes/constraint_object_is_equal_with_exceptions.php @@ -0,0 +1,86 @@ +. + +/** + * Constraint that checks a simple object with an isEqual constrain, allowing for exceptions to be made for some fields. + * + * @package core + * @category phpunit + * @copyright 2015 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +/** + * Constraint that checks a simple object with an isEqual constrain, allowing for exceptions to be made for some fields. + * + * @package core + * @category phpunit + * @copyright 2015 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class phpunit_constraint_object_is_equal_with_exceptions extends PHPUnit_Framework_Constraint_IsEqual { + + /** + * @var array $keys The list of exceptions. + */ + protected $keys = array(); + + /** + * Add an exception for the named key to use a different comparison + * method. Any assertion provided by PHPUnit_Framework_Assert is + * acceptable. + * + * @param string $key The key to except. + * @param string $comparator The assertion to use. + */ + public function add_exception($key, $comparator) { + $this->keys[$key] = $comparator; + } + + /** + * Evaluates the constraint for parameter $other + * + * If $shouldreturnesult is set to false (the default), an exception is thrown + * in case of a failure. null is returned otherwise. + * + * If $shouldreturnesult is true, the result of the evaluation is returned as + * a boolean value instead: true in case of success, false in case of a + * failure. + * + * @param mixed $other Value or object to evaluate. + * @param string $description Additional information about the test + * @param bool $shouldreturnesult Whether to return a result or throw an exception + * @return mixed + * @throws PHPUnit_Framework_ExpectationFailedException + */ + public function evaluate($other, $description = '', $shouldreturnesult = false) { + foreach ($this->keys as $key => $comparison) { + if (isset($other->$key) || isset($this->value->$key)) { + // One of the keys is present, therefore run the comparison. + PHPUnit_Framework_Assert::$comparison($this->value->$key, $other->$key); + + // Unset the keys, otherwise the standard evaluation will take place. + unset($other->$key); + unset($this->value->$key); + } + } + + // Run the parent evaluation (isEqual). + return parent::evaluate($other, $description, $shouldreturnesult); + } + +} diff --git a/lib/phpunit/lib.php b/lib/phpunit/lib.php index daccb1785ff9b..f271690da516a 100644 --- a/lib/phpunit/lib.php +++ b/lib/phpunit/lib.php @@ -37,5 +37,6 @@ require_once(__DIR__.'/classes/advanced_testcase.php'); require_once(__DIR__.'/classes/unittestcase.php'); require_once(__DIR__.'/classes/hint_resultprinter.php'); // Loaded here because phpunit.xml does not support relative links for printerFile. +require_once(__DIR__.'/classes/constraint_object_is_equal_with_exceptions.php'); require_once(__DIR__.'/../testing/classes/test_lock.php'); require_once(__DIR__.'/../testing/classes/tests_finder.php');