Skip to content

Commit

Permalink
Merge pull request nette#133 from MartinMystikJonas/custom-fail-messages
Browse files Browse the repository at this point in the history
Optional custom fail messages in asserts
  • Loading branch information
dg committed Aug 5, 2015
2 parents 0807e28 + 425e1d1 commit 8267b22
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 40 deletions.
94 changes: 54 additions & 40 deletions src/Framework/Assert.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ class Assert
* Checks assertion. Values must be exactly the same.
* @return void
*/
public static function same($expected, $actual)
public static function same($expected, $actual, $description = NULL)
{
self::$counter++;
if ($actual !== $expected) {
self::fail('%1 should be %2', $actual, $expected);
self::fail(self::describe('%1 should be %2', $description), $actual, $expected);
}
}

Expand All @@ -60,11 +60,11 @@ public static function same($expected, $actual)
* Checks assertion. Values must not be exactly the same.
* @return void
*/
public static function notSame($expected, $actual)
public static function notSame($expected, $actual, $description = NULL)
{
self::$counter++;
if ($actual === $expected) {
self::fail('%1 should not be %2', $actual, $expected);
self::fail(self::describe('%1 should not be %2', $description), $actual, $expected);
}
}

Expand All @@ -73,11 +73,11 @@ public static function notSame($expected, $actual)
* Checks assertion. The identity of objects and the order of keys in the arrays are ignored.
* @return void
*/
public static function equal($expected, $actual)
public static function equal($expected, $actual, $description = NULL)
{
self::$counter++;
if (!self::isEqual($expected, $actual)) {
self::fail('%1 should be equal to %2', $actual, $expected);
self::fail(self::describe('%1 should be equal to %2', $description), $actual, $expected);
}
}

Expand All @@ -86,11 +86,11 @@ public static function equal($expected, $actual)
* Checks assertion. The identity of objects and the order of keys in the arrays are ignored.
* @return void
*/
public static function notEqual($expected, $actual)
public static function notEqual($expected, $actual, $description = NULL)
{
self::$counter++;
if (self::isEqual($expected, $actual)) {
self::fail('%1 should not be equal to %2', $actual, $expected);
self::fail(self::describe('%1 should not be equal to %2', $description), $actual, $expected);
}
}

Expand All @@ -99,19 +99,19 @@ public static function notEqual($expected, $actual)
* Checks assertion. Values must contains expected needle.
* @return void
*/
public static function contains($needle, $actual)
public static function contains($needle, $actual, $description = NULL)
{
self::$counter++;
if (is_array($actual)) {
if (!in_array($needle, $actual, TRUE)) {
self::fail('%1 should contain %2', $actual, $needle);
self::fail(self::describe('%1 should contain %2', $description), $actual, $needle);
}
} elseif (is_string($actual)) {
if ($needle !== '' && strpos($actual, $needle) === FALSE) {
self::fail('%1 should contain %2', $actual, $needle);
self::fail(self::describe('%1 should contain %2', $description), $actual, $needle);
}
} else {
self::fail('%1 should be string or array', $actual);
self::fail(self::describe('%1 should be string or array', $description), $actual);
}
}

Expand All @@ -120,103 +120,109 @@ public static function contains($needle, $actual)
* Checks assertion. Values must not contains expected needle.
* @return void
*/
public static function notContains($needle, $actual)
public static function notContains($needle, $actual, $description = NULL)
{
self::$counter++;
if (is_array($actual)) {
if (in_array($needle, $actual, TRUE)) {
self::fail('%1 should not contain %2', $actual, $needle);
self::fail(self::describe('%1 should not contain %2', $description), $actual, $needle);
}
} elseif (is_string($actual)) {
if ($needle === '' || strpos($actual, $needle) !== FALSE) {
self::fail('%1 should not contain %2', $actual, $needle);
self::fail(self::describe('%1 should not contain %2', $description), $actual, $needle);
}
} else {
self::fail('%1 should be string or array', $actual);
self::fail(self::describe('%1 should be string or array', $description), $actual);
}
}


/**
* Checks TRUE assertion.
* @param mixed actual
* @param string fail message
* @return void
*/
public static function true($actual)
public static function true($actual, $description = NULL)
{
self::$counter++;
if ($actual !== TRUE) {
self::fail('%1 should be TRUE', $actual);
self::fail(self::describe('%1 should be TRUE', $description), $actual);
}
}


/**
* Checks FALSE assertion.
* @param mixed actual
* @param string fail message
* @return void
*/
public static function false($actual)
public static function false($actual, $description = NULL)
{
self::$counter++;
if ($actual !== FALSE) {
self::fail('%1 should be FALSE', $actual);
self::fail(self::describe('%1 should be FALSE', $description), $actual);
}
}


/**
* Checks NULL assertion.
* @param mixed actual
* @param string fail message
* @return void
*/
public static function null($actual)
public static function null($actual, $description = NULL)
{
self::$counter++;
if ($actual !== NULL) {
self::fail('%1 should be NULL', $actual);
self::fail(self::describe('%1 should be NULL', $description), $actual);
}
}


/**
* Checks Not a Number assertion.
* @param mixed actual
* @param string fail message
* @return void
*/
public static function nan($actual)
public static function nan($actual, $description = NULL)
{
self::$counter++;
if (!is_float($actual) || !is_nan($actual)) {
self::fail('%1 should be NAN', $actual);
self::fail(self::describe('%1 should be NAN', $description), $actual);
}
}


/**
* Checks truthy assertion.
* @param mixed actual
* @param string fail message
* @return void
*/
public static function truthy($actual)
public static function truthy($actual, $description = NULL)
{
self::$counter++;
if (!$actual) {
self::fail('%1 should be truthy', $actual);
self::fail(self::describe('%1 should be truthy', $description), $actual);
}
}


/**
* Checks falsey (empty) assertion.
* @param mixed actual
* @param string fail message
* @return void
*/
public static function falsey($actual)
public static function falsey($actual, $description = NULL)
{
self::$counter++;
if ($actual) {
self::fail('%1 should be falsey', $actual);
self::fail(self::describe('%1 should be falsey', $description), $actual);
}
}

Expand All @@ -225,16 +231,17 @@ public static function falsey($actual)
* Checks if subject has expected count.
* @param int expected count
* @param mixed subject
* @param string fail message
* @return void
*/
public static function count($count, $value)
public static function count($count, $value, $description = NULL)
{
self::$counter++;
if (!$value instanceof \Countable && !is_array($value)) {
self::fail('%1 should be array or countable object', $value);
self::fail(self::describe('%1 should be array or countable object', $description), $value);

} elseif (count($value) !== $count) {
self::fail('Count %1 should be %2', count($value), $count);
self::fail(self::describe('Count %1 should be %2', $description), count($value), $count);
}
}

Expand All @@ -243,27 +250,27 @@ public static function count($count, $value)
* Checks assertion.
* @return void
*/
public static function type($type, $value)
public static function type($type, $value, $description = NULL)
{
self::$counter++;
if (!is_object($type) && !is_string($type)) {
throw new \Exception('Type must be a object or a string.');

} elseif ($type === 'list') {
if (!is_array($value) || ($value && array_keys($value) !== range(0, count($value) - 1))) {
self::fail("%1 should be $type", $value);
self::fail(self::describe("%1 should be $type", $description), $value);
}

} elseif (in_array($type, array('array', 'bool', 'callable', 'float',
'int', 'integer', 'null', 'object', 'resource', 'scalar', 'string'), TRUE)
) {
if (!call_user_func("is_$type", $value)) {
self::fail(gettype($value) . " should be $type");
self::fail(self::describe(gettype($value) . " should be $type", $description));
}

} elseif (!$value instanceof $type) {
$actual = is_object($value) ? get_class($value) : gettype($value);
self::fail("$actual should be instance of $type");
self::fail(self::describe("$actual should be instance of $type", $description));
}
}

Expand Down Expand Up @@ -385,17 +392,18 @@ public static function error($function, $expectedType, $expectedMessage = NULL)
* %f% floating point number
* %h% one or more HEX digits
* @param string mask|regexp; only delimiters ~ and # are supported for regexp
* @param string
* @param string actual
* @param string fail message
* @return void
*/
public static function match($pattern, $actual)
public static function match($pattern, $actual, $description = NULL)
{
self::$counter++;
if (!is_string($pattern)) {
throw new \Exception('Pattern must be a string.');

} elseif (!is_scalar($actual) || !self::isMatching($pattern, $actual)) {
self::fail('%1 should match %2', $actual, rtrim($pattern));
self::fail(self::describe('%1 should match %2', $description), $actual, rtrim($pattern));
}
}

Expand All @@ -404,15 +412,15 @@ public static function match($pattern, $actual)
* Compares results using mask sorted in file.
* @return void
*/
public static function matchFile($file, $actual)
public static function matchFile($file, $actual, $description = NULL)
{
self::$counter++;
$pattern = @file_get_contents($file); // @ is escalated to exception
if ($pattern === FALSE) {
throw new \Exception("Unable to read file '$file'.");

} elseif (!is_scalar($actual) || !self::isMatching($pattern, $actual)) {
self::fail('%1 should match %2', $actual, rtrim($pattern));
self::fail(self::describe('%1 should match %2', $description), $actual, rtrim($pattern));
}
}

Expand All @@ -432,6 +440,12 @@ public static function fail($message, $actual = NULL, $expected = NULL)
}


private static function describe($reason, $description)
{
return ($description ? $description . ': ' : '') . $reason;
}


public static function with($obj, \Closure $closure)
{
return $closure->bindTo($obj, $obj)->__invoke();
Expand Down
8 changes: 8 additions & 0 deletions tests/Framework/Assert.contains.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,11 @@ Assert::exception(function () {
Assert::exception(function () {
Assert::notContains('', '1');
}, 'Tester\AssertException', "'1' should not contain ''");

Assert::exception(function () {
Assert::contains('a', '1', 'Custom description');
}, 'Tester\AssertException', "Custom description: '1' should contain 'a'");

Assert::exception(function () {
Assert::notContains('1', '1', 'Custom description');
}, 'Tester\AssertException', "Custom description: '1' should not contain '1'");
4 changes: 4 additions & 0 deletions tests/Framework/Assert.count.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ Assert::exception(function () {
Assert::exception(function () {
Assert::count(1, new \Exception('lorem ipsum'));
}, 'Tester\AssertException', 'Exception Exception: lorem ipsum should be array or countable object');

Assert::exception(function () {
Assert::count(1, array(1, 2, 3), 'Custom description');
}, 'Tester\AssertException', 'Custom description: Count 3 should be 1');
8 changes: 8 additions & 0 deletions tests/Framework/Assert.equal.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,11 @@ Assert::exception(function () {
$rec[] = & $rec;
Assert::equal($rec, $rec);
}, 'Exception', 'Nesting level too deep or recursive dependency.');

Assert::exception(function () {
Assert::equal(true, false, 'Custom description');
}, 'Tester\AssertException', 'Custom description: %a% should be equal to %a%');

Assert::exception(function () {
Assert::notEqual(true, true, 'Custom description');
}, 'Tester\AssertException', 'Custom description: %a% should not be equal to %a%');
4 changes: 4 additions & 0 deletions tests/Framework/Assert.false.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ foreach ($notFalse as $value) {
Assert::false($value);
}, 'Tester\AssertException', '%a% should be FALSE');
}

Assert::exception(function () {
Assert::false(true, 'Custom description');
}, 'Tester\AssertException', 'Custom description: %a% should be FALSE');
8 changes: 8 additions & 0 deletions tests/Framework/Assert.match.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,11 @@ Assert::exception(function () {


Assert::matchFile(__DIR__ . '/Assert.matchFile.txt', '! Hello !');

Assert::exception(function () {
Assert::match('a', 'b', 'Custom description');
}, 'Tester\AssertException', 'Custom description: %A% should match %A%');

Assert::exception(function () {
Assert::matchFile(__DIR__ . '/Assert.matchFile.txt', '! Not match !', 'Custom description');
}, 'Tester\AssertException', 'Custom description: %A% should match %A%');
4 changes: 4 additions & 0 deletions tests/Framework/Assert.nan.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ foreach ($notNan as $value) {
Assert::nan($value);
}, 'Tester\AssertException', '%a% should be NAN');
}

Assert::exception(function () {
Assert::nan(1, 'Custom description');
}, 'Tester\AssertException', 'Custom description: %a% should be NAN');
4 changes: 4 additions & 0 deletions tests/Framework/Assert.null.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ foreach ($notNull as $value) {
Assert::null($value);
}, 'Tester\AssertException', '%a% should be NULL');
}

Assert::exception(function () {
Assert::null(true, 'Custom description');
}, 'Tester\AssertException', 'Custom description: %a% should be NULL');
8 changes: 8 additions & 0 deletions tests/Framework/Assert.same.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,11 @@ Assert::exception(function () {
$rec[] = & $rec;
Assert::same($rec, array());
}, 'Tester\AssertException');

Assert::exception(function () {
Assert::same(true, false, 'Custom description');
}, 'Tester\AssertException', 'Custom description: %a% should be %a%');

Assert::exception(function () {
Assert::notSame(true, true, 'Custom description');
}, 'Tester\AssertException', 'Custom description: %a% should not be %a%');
4 changes: 4 additions & 0 deletions tests/Framework/Assert.true.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ foreach ($notTrue as $value) {
Assert::true($value);
}, 'Tester\AssertException', '%a% should be TRUE');
}

Assert::exception(function () {
Assert::true(false, 'Custom description');
}, 'Tester\AssertException', 'Custom description: %a% should be TRUE');
Loading

0 comments on commit 8267b22

Please sign in to comment.