Thursday, April 5, 2012

Write Your First Unit Test Using PHPUnit

Hi All. We will discuss how to write your first unit test case using PHPUnit. If you are not configured your testing environment yet, refer my first post

Unit testing is a method of testing that verifies the individual units of source code are working properly. Normally we are considering a function (method) as our unit of source code.

Assume we are writing a function to add two numbers in class operation.

Copy the above code into a empty text file and name it as operation.php. Now we need to write a test case for function add(); Function add() accepting two parameters and returning the addition of those. So what we have to test is passing two values to the add method and check whether we are getting the expected output.

Create the operationTest.php file and copy the above code into it. The class should extend the PHPUnit_Framework_TestCase. In function testAdd(), it passes two values for the add method and getting the return value. As we passes 2 and 3 the return valued should be 5. We can verify it using assertions. We used assertEquals() to check the return value and the expected values are equals. If it equals the test will pass. 

Running the Unit Test

Place the above two file in a same folder and run the following command.
$ phpunit operationTest.php

You will get the following.

PHPUnit 3.6.10 by Sebastian Bergmann.
.
Time: 0 seconds, Memory: 3.50Mb
OK (1 test, 1 assertion)

For each test run, the PHPUnit command-line tool prints one character to indicate progress.
.         Printed when the test succeeds.
F        Printed when an assertion fails while running the test method.
E        printed when an error occurs while running the test method.
S        Printed when the test has been skipped.
I         Printed when the test is marked as being incomplete or not yet implemented.
              
Change the expected value into some other value and run the test. You will have test failure. 

PHPUnit 3.6.10 by Sebastian Bergmann.
F
Time: 0 seconds, Memory: 3.50Mb
There was 1 failure:
1) operationTest::testAdd
Failed asserting that 2 matches expected 5.
/var/www/codemix/operationTest.php:15
FAILURES!
Change the method in to some other name and run the test. You will have fetal error.
PHPUnit 3.6.10 by Sebastian Bergmann.
PHP Fatal error:  Call to undefined method operation::sum() in
/var/www/codemix/operationTest.php on line 14.   .............

We can write multiple tests for one method. Add following test method to operationTest.php to test addition of decimals values. 

Testing Negative Scenario

In good test cases there should be test cases for testing the success scenarios as well as negative scenarios. Add following test cases to operationTest.php. It checks the return value is not equal to a invalid output. 


Keep writing test cases and get them passed. Try following assertion methods. 

assertTrue($x)Fail if $x is false
assertFalse($x)Fail if $x is true
assertNull($x)Fail if $x is set
assertNotNull($x)Fail if $x not set
assertIsA($x, $t)Fail if $x is not the class or type $t
assertNotA($x, $t)Fail if $x is of the class or type $t
assertEqual($x, $y)Fail if $x == $y is false
assertNotEqual($x, $y)Fail if $x == $y is true
assertWithinMargin($x, $y, $m)Fail if abs($x - $y) < $m is false
assertOutsideMargin($x, $y, $m)Fail if abs($x - $y) < $m is true
assertIdentical($x, $y)Fail if $x == $y is false or a type mismatch
assertNotIdentical($x, $y)Fail if $x == $y is true and types match
assertReference($x, $y)Fail unless $x and $y are the same variable
assertClone($x, $y)Fail unless $x and $y are identical copies
assertPattern($p, $x)Fail unless the regex $p matches $x
assertNoPattern($p, $x)Fail if the regex $p matches $x
expectError($x)Fail if matching error does not occur
expectException($x)Fail if matching exception is not thrown
ignoreException($x)Swallows any upcoming matching exception
assert($e)Fail on failed expectation object $e

We will look in to more advanced techniques of unit testing. Write a method, write a test case for that and enjoying by get passing it. :)