I am using PHPUnit to test my code But when i use assertTrue phpunit behaves expectly. Is this normal beahviour of phpunit or not. I got the following error.
Failed asserting that 1 is true.
1 is not a "real" true value. You can try this :
true == 1 // return true
true === 1 // return false
false == null // return true
false === null // return false
PHPUnit use === in assertTrue. So if you do assertTrue(1);, PHPUnit just stop because the assertion is false.
Related
I have a boolean field that is represented by 0 and 1 in my database.
if ($request->input('submitted')) {
// do code
}
This has been working because it's only been setting the field to 1 (true) but now there's a new flow that can revert the submission.
It has not been setting it back to 0 when I pass the value 0 in from the frontend and I assume it's because that condition is getting skipped since 0 would eval to null.
Is the best way to handle it:
if (isset($request->input('submitted'))) {
// do code
}
or would strictly checking against null work better:
if ($request->input('submitted') !== null) {
// do code
}
The simply approach parse your input to a boolean.
if ((bool) $request->input('submitted')) {
This will create the following results. Therefor removing your edge case.
(bool) "1" // true
(bool) "1" // false
An alternative approach is to use inbuilt PHP filter, it will parse a lot of cases more notably "true" and "false" to true and false.
if (filter_var($request->input('submitted'), FILTER_VALIDATE_BOOLEAN)) {
I am reading a book and the author is using the following function. I don't understand the benefit of the equal operator. Can anybody please explain the reason for using the equal operator.
public function isDiscounted()
{
return 0 == $this->getRow()->discountPercent ? false : true;
}
Would it not be easier to go for
public function isDiscounted()
{
return $this->getRow()->discountPercent ? false : true;
}
?
Best regards,
Herbert
In your example you would need to swap the true and false:
return $this->getRow()->discountPercent ? true : false;
However you could just cast the integer return to a boolean:
return (bool)$this->getRow()->discountPercent;
Or even:
return 0 != $this->getRow()->discountPercent;
There's no need for the ternary returning true or false.
The benefit of the == operator is to make the program's intent clearer, that you're comparing a numeric variable with zero. It's equivalent to writing:
if (0 == $this->getRow()->discountPercent) {
return false;
} else {
return true;
}
You could also write it as:
return $this->getRow()->discountPercent ? true : false;
but this suggests that discountPercent is a boolean value, not numeric. Similarly, you could write:
return !$this->getRow()->discountPercent;
but this also suggests that it's boolean. While PHP is flexible with types like this, treating all non-falsy values as true, the original code is easier for human readers to understand.
In PHP you can do a loose comparison or a strict comparison. It really depends what you are trying to compare for, sometimes the loose is fine, sometimes you need it to be strict.
loose vs strict
/** loose **/
0 == 0; // true
0 == false; // true
0 == ''; // true
0 == null; // true
/** strict **/
0 === 0; // true
0 === false; // false
0 === ''; // false
0 === null; // false
as it pertains to your example
/**
* When doing the loose comparison, anything is isn't
* 0, false, '', or null will always evaluate to true.
*
* So for instance:
*/
'iamateapot' == true; // true
'false' == true; // true, this is true because it's a string of false not a boolean of false;
0 == true; // false;
In your particular case you are doing
$this->getRow()->discountPercent ? false : true;
Which is doing a loose comparison, my preference is to always specify what you are comparing against, so your first example would be what I would personally choose.
No, it's not easier to go for
return $this->getRow()->discountPercent ? false : true
In fact, it's wrong. You are supposed to return false if discountPercent is zero. In your suggested code, if discountPercent is zero, it will evaluate to false since it's used as a condition and return true.
If you truly want to keep the same logic but make it shorter the best way to go about it would be:
return $this->getRow()->discountPercent != 0
I have a rule I always follow: If the result of a conditional statement is a boolean, then return/condition itself. Also, I disagree that writing:
return 0 == $this->getRow()->discountPercent ? false : true;
makes the code more readable. If we go by what the function is supposed to do, I would write it something like this:
return $this->getRow()->discountPercent > 0
which clearly indicates that if discountPercent has a value greater than zero then it is discounted. Simple, precise and clear. It also takes care of negative values then.
I'm modelling an access function that should return boolean value based on next structure on nested array, which contains only boolean values:
based on dimension, comparison of the should be made either OR or AND type
first level is OR, next level is AND, next level is OR and so on
final result should return TRUE or FALSE
For example I have these arrays with expected results:
array(TRUE) -> TRUE
array(FALSE) -> FALSE
evidently...
array(TRUE, FALSE) -> TRUE
because of TRUE | FALSE
array(TRUE, array(FALSE)) -> TRUE
because of TRUE | (FALSE)
array(FALSE, array(FALSE, TRUE)) -> FALSE
because of FALSE | (FALSE && TRUE)
array(FALSE, array(TRUE, array(FALSE, TRUE))) -> TRUE
because of FALSE | (TRUE && (FALSE | TRUE))
What I'm doing here is just changing comparison method on every other level of the nested array.
PHP language example would be nice, but any prototype that I can transfer to PHP is accepted as an answer.
This is an example of mutual-recursion, using the array_reduce function
do_or applies the OR operator on the entire array
do_and applies the AND operator on the entire array
if an element of the array is an array itself, the functions apply each other
The Code:
function do_or($x,$y)
{
if (is_array($y))
{
if (empty($y))
{$y=FALSE;}
else
{$y=array_reduce($y,"do_and",TRUE);}
}
return $x||$y;
}
function do_and($x,$y)
{
if (is_array($y))
{
if (empty($y))
{$y=TRUE;}
else
{$y=array_reduce($y,"do_or",FALSE);}
}
return $x && $y;
}
$answer=array_reduce($arr,"do_or",FALSE);
This code could be optimized, but I guess it illustrates the idea
In the PHP documentation for json_decode it says it can return TRUE,FALSE,NULL.
Could some help me understand when it would return FALSE? I understand invalid JSON will return NULL, but when would the other two be returned if not the actual JSON value?
Thanks
JSON format definition clearly shows all possible values and their representations:
A value can be a string in double quotes, or a number, or true or
false or null, or an object or an array.
Both objects and arrays have special syntax in JSON representation (wrapped in {} and [] respectively), so they can't be mixed up with false in any case. The same goes with string - it's wrapped in "" (double quotation marks). As for Numbers, they have to contain at least one digit - so cannot be confused with false (and true and null) too.
So that leaves us with the only case: when json_encode processes an object having redefined its JSON representation. For example (PHP 5.4+):
class FalsyFoo implements JsonSerializable {
public $foo;
public function __construct($f) {
$this->foo = $f;
}
public function jsonSerialize() {
return false;
}
}
$f = new FalsyFoo(true);
$fj = json_encode($f);
var_dump( $fj ); // string(5) 'false'
var_dump( json_decode($fj) ); // bool(false)
Technically, we still work with false value here, but the source is obviously different.
If you're still not convinced, check the source code of json_decode, which calls php_json_decode_ex after checking the arguments. This, in turn, calls parse_JSON_ex first, which operates over the predefined state transition table; the latter has only one set of states leading to false value as result. If this call fails somehow, value is checked directly:
if (str_len == 4) {
if (!strcasecmp(str, "null")) {
/* We need to explicitly clear the error
because its an actual NULL and not an error */
jp->error_code = PHP_JSON_ERROR_NONE;
RETVAL_NULL();
} else if (!strcasecmp(str, "true")) {
RETVAL_BOOL(1);
}
} else if (str_len == 5 && !strcasecmp(str, "false")) {
RETVAL_BOOL(0);
}
... and that's the only case when return_value is set to boolean.
The documentation says that values true, false and null (case-insensitive) are returned as TRUE, FALSE and NULL respectively. This means that if the booleans true orfalse are in the object to be encoded, they will be shows as TRUE or FALSE, and the same for null. For example:
json_decode('["hello",true]');
would return:
["hello",TRUE]
It doesn't mean that json_decode will return values of true, false, or null
Does anyone know a reliable way to distinguish between FALSE and NULL with PHPUnit?
I'm trying to distinguish from NULL and FALSE in return values in my assertions.
This fails:
$this->assertNotEquals(FALSE, NULL);
And these assertions pass:
$this->assertFalse(NULL);
$this->assertNull(FALSE);
Edit: For some context, this is to distinguish between an error state (FALSE) versus an empty result (NULL). To ensure the function is returning properly, I need to distinguish between the two.
Thanks
Edit...
As per some of the problems regarding what I am testing, I'm adding the tests.
Class testNullFalse extends PHPUnit_Framework_TestCase{
public function test_null_not_false (){
$this->assertNotEquals(FALSE, NULL, "False and null are not the same");
}
public function test_null_is_false (){
$this->assertFalse(NULL, "Null is clearly not FALSE");
}
public function test_false_is_null (){
$this->assertNull(FALSE, "False is clearly not NULL");
}
public function test_false_equals_null(){
$this->assertEquals(FALSE, NULL, "False and null are not equal");
}
public function test_false_sameas_null(){
$this->assertSame(FALSE, NULL, "False and null are not the same");
}
public function test_false_not_sameas_null(){
$this->assertNotSame(FALSE, NULL, "False and null are not the same");
}
}
And the results.
PHPUnit 3.5.10 by Sebastian Bergmann.
FFF.F.
Time: 0 seconds, Memory: 5.50Mb
There were 4 failures:
1) testNullFalse::test_null_not_false
False and null are not the same
Failed asserting that <null> is not equal to <boolean:false>.
2) testNullFalse::test_null_is_false
Null is clearly not FALSE
Failed asserting that <null> is false.
3) testNullFalse::test_false_is_null
False is clearly not NULL
Failed asserting that <boolean:false> is null.
4) testNullFalse::test_false_sameas_null
False and null are not the same
<null> does not match expected type "boolean".
FAILURES!
Tests: 6, Assertions: 6, Failures: 4.
These assertions use == which will perform type coercion. Hamcrest has identicalTo($value) which uses ===, and I believe PHPUnit has assertSame($expected, $actual) which does the same.
self::assertSame(false, $dao->getUser(-2));
Update: In answer to your comment, "It can be NULL or an object":
$user = $dao->getUser(-2);
self::assertTrue($user === null || is_object($user));
Using Hamcrest assertions is a little more expressive, especially in the event of a failure:
assertThat($dao->getUser(-2), anyOf(objectValue(), nullValue()));
Execute the comparison yourself, and use the strict type operator.
$this->assertTrue(false !== null);
http://php.net/operators.comparison
#David is right with assertSame (+1), it will do === strict comparison for you.
But let me ask you:
Which version of phpunit are you using?
This assertion:
$this->assertFalse(null);
should produce and error!
Sample Code:
<?php
class mepTest extends PHPUnit_Framework_TestCase {
public function testFalseNull() {
$this->assertFalse(null);
}
public function testNullFalse() {
$this->assertNull(false);
}
}
Results in:
phpunit mepTest.php
PHPUnit 3.5.12 by Sebastian Bergmann.
FF
Time: 0 seconds, Memory: 3.00Mb
There were 2 failures:
1) mepTest::testFalseNull
Failed asserting that <null> is false.
/home/.../mepTest.php:6
2) mepTest::testNullFalse
Failed asserting that <boolean:false> is null.
/home/.../mepTest.php:10
FAILURES!
Tests: 2, Assertions: 2, Failures: 2.