An In-Depth Look At PHP Unit Assertions

An In-Depth Look At PHP Unit Assertions
COMMENTS ()
Tweet

A Definitive Guide to Testing PHP Applications with PHP Unit outlines the core to-dos for getting started with unit testing in PHP. If you would like to implement the ideas presented in this blog, please ensure that you have scanned the definitive-guide blog and have the required knowledge of configuring php unit, executing it and writing your first test. PHP Unit – Getting Started briefly mentions the concept of ‘Assertions’, which is the heart of Unit Testing. Since, it’s the assertion which eventually validates your code. This blog takes a look at possible loopholes when writing your assertions and mentions the techniques to avoid it. For an exhaustive list and implementation detail of assertion methods, please refer to the Assertions in official docs.

 

assertEqual vs assertSame

This is a common pitfall that many developers fail to realize. You might be happily passing all test cases with assertEquals where you should have used assertSame, and similarly you might be completely clueless on why an assertion is getting failed with assertSame, when the values are visibly equal in every way.

This is a common pitfall that many developers fail to realize. You might be happily passing all test cases with assertEquals where you should have used assertSame, and similarly you might be completely clueless on why an assertion is getting failed with assertSame, when the values are visibly equal in every way.

assertEquals corresponds to the == operator. This means that int(5) is equal to 5.0 and “5”. The data type can be crucial in many applications, but using assertEquals would simply overlook this fact.

Similarly an object with a value “6” and an object with a value 6.0 are equal for assertEquals. Equivalently, an array [5, 6, 7] and an array [5,6.0,7] are equal as well.

assertSame corresponds to the === operator, which does strict comparison and only returns True when both the value and type are same. For objects, this compares that both compared variables point to exactly the same instance, not different instances of same class with same values. Hence, using assertSame with objects can cause headaches if we only intend to have similar instances of the class with same values.

Note: array[5,6,7] and array[6,5,7] are not equal for assertEquals. If you only intend to compare array contents irrespective of their order, sort arrays before comparing.

 

assertTrue/False vs assertEquals

This highlights the same issue as in above but has been separated since PHP Unit provides distinct methods to assert True/False values and boolean comparison mostly dictates the application flow.

For assertEquals, False is equal to any of the falsy values in PHP. Thus, assertEquals returns true for False compared to 0/0.0/””/”0”/ array()/ [ ]/ null. Likewise, all values besides these would be stated as equal to True if we use assertEquals. Therefore, the right operators to use are assertTrue and assertFalse, which ensure that we have exactly the expected boolean operator in response.

 

Comparing Objects

The behavior of object assertion using assertEquals and assertSame has been briefly stated under the first heading. In short, comparing objects with assertEquals does not verify that internal values of an object are strictly equal or not. On the other hand, using assertSame only compares that the variables refer to exactly the same object instance or not. Thus, we are left with the issue that how exactly do we compare that two objects are different instances of the same class and have strictly equal internal values. A common use case might be validating the JSON payload against the expected payload.

One way out of it, could be comparing and asserting individual values from the both objects but this can be very time consuming and cluttered. And could be troublesome given we have a change in payload and there are handful of test cases written to assert the same payload. The elegant way to handle this is to write a recursive method that iterates against all object values and performs strict comparison against its corresponding value. Similarly, if there are nested objects, comparing them in a similar fashion.

We have a PHP library written for solely for this purpose called Parity. Checkout here: Github

The issue unit testers might face while using this is failure representation. PHP Unit by default outputs nice color coded failure output which exactly shows the difference between expected and actual object properties, but when using Parity, there is no default way to output failure this way.

The hack could be using PHP library Diff, which is internally used by PHP Unit to output test results.

By using diff, we can generate the output difference string and pass this string to any of the assertion methods of PHP Unit, which accept a custom error message to display when the test case fails.

Please see how Optimizely PHP SDK exactly does that for comparing it’s event payloads:
https://github.com/optimizely/php-sdk/blob/master/tests/EventTests/EventBuilderTest.php#L90

CALL

USA408 365 4638

VISIT

1301 Shoreway Road, Suite 160,

Belmont, CA 94002

Contact us

Whether you are a large enterprise looking to augment your teams with experts resources or an SME looking to scale your business or a startup looking to build something.
We are your digital growth partner.

Tel: +1 408 365 4638
Support: +1 (408) 512 1812