Setting Up and Using PHPUnit

Contents

PHPUnit

In the last decade, PHP has developed from a niche language for adding dynamic functionality to small websites to a powerful tool making strong inroads into large-scale, business-critical Web systems. Financial institutions such as banks and insurance companies use PHP, for instance, to develop and maintain solutions for Basel II Credit Rating. Critical business logic like this needs to work correctly. To make code testing viable, good tool support is needed. This is where PHPUnit comes into play. It provides both a framework that makes the writing of tests easy as well as the functionality to easily run the tests and analyse their results. But how do you ensure that it does? You test it, of course. For further information, visit PHPUnit website.

Installing PHPUnit

PHPUnit is a part of the PEAR Packages. PEAR is the backbone of running PhPunit since first being intergrated into PHP. Instructions to installing PhPUnit can be easily found at Installing PhPUnit:

Writing Test Code for PHPUnit

Testing with PHPUnit is simple to learn and implement. The basic idea is to check that the codes written behave as expected, and to run a suite of tests, runnable code-fragments that automatically test the correctness of parts (individual units) of the software. These runnable code-fragments are called unit tests.

The goal of using automated tests is to make fewer mistakes. While the codes might still not be perfect, even with excellent tests, it is likely to see a dramatic reduction in defects once automated tests are run. This makes the process of quality assurance and usability testing much easier.

Writing tests

Each class in your code should have a corresponding test class called [YourClassname]Test. Make sure your test class extends PHPUnit_Framework_TestCase. Inside these classes, you can define setUp() and tearDown() functions, which will be called before and after each test and can be used to setup the environment for the test. This is generally helpful to test functions which make database queries and manipulate with the data therein. So, the setup() functions help in setting up the insertion and anyother queries that would manipulate the data in the database. teardown() function on the other hand, would reverse all these changes so that the database remains intact after the tests are over. Here is an example from one of the unit testing classes from the Voulnteer Management module in Sahana:

class daoTest extends PHPUnit_Framework_TestCase {
/**
 * Sets up the fixture, for example, open a network connection.
 * This method is called before a test is executed.
 *
 * @access protected
 */
 
protected function setUp() {
//Include the ADOdb Library
  	
 global $global,$dao;
 $global=array('approot'=>realpath(dirname(__FILE__)).'/../../../');
 require_once($global['approot'].'3rd/adodb/adodb.inc.php');
 require_once($global['approot'].'mod/vm/main.inc');

 //Make the connection to $global['db']
 $global['db'] = NewADOConnection('mysql');
 $global['db']->Connect(TEST_DB_HOST, TEST_DB_USER,TEST_DB_PASSWD,TEST_DB_NAME);
 $dao = new DAO($global['db']);
 $this->fixture = $dao;

 //insertion queries or queries that make changes on the test database:
 $this->fixture->execute("INSERT INTO users (p_uuid, user_name) VALUES ('test1', 'user')");
 $this->fixture->execute("INSERT INTO users (p_uuid, user_name) VALUES ('test2', 'crew')");
 ...
 ...

//the teardown() to remove the changes made to the database:
/** 
 * Tears down the fixture, for example, close a network connection.
 * This method is called after a test is executed.
 *
 * @access protected
 */

protected function tearDown() {
 global $time; 
 $this->fixture->execute("DELETE FROM users (p_uuid, user_name) VALUES ('test1', 'user')");
 $this->fixture->execute("DELETE FROM users (p_uuid, user_name) VALUES ('test2', 'crew')");
 ...
 ...

The setup() and teardown() functions are followed by the test functions. Each test function within the class must have test in front of the function name. For better visual instructions on writing PhPUnit tests, visit the example site. There is an example here from the Volunteer Management module in Sahana again:

public function testGetPersonName()
  {
     $test = $this->fixture->getPersonName('test1');
     $this->assertEquals($test, 'Volunteer1');
     
     $test1 = $this->fixture->getPersonName('test2');
     $this->assertEquals($test1, 'Volunteer2');
     
     $test2 = $this->fixture->getPersonName('test3');
     $this->assertFalse($test2);
  }

This is the unit test code written for a fuction called getPersonName($p_uiuid):

function getPersonName($p_uuid) 
  {
     $result = $this->execute("SELECT full_name FROM person_uuid WHERE p_uuid ='$p_uuid'");
     if(!$result->fields)
          return false;
     return $result->fields['full_name'];
  }

So, basically, the unit test functions provide the actual functions with test cases and expected outputs, and makes comparisons with the output from the functions with the expected ones to assert if they were equal or not.

PHPUnit Testing

The PHPUnit command-line test runner can be invoked through the phpunit command. Command operations for running PHPUnit for code testing

For extra information and examples on Orgainizing Test Suites can be found here