PHPUnit Automated Unit Testing Framework. By : Varun Taliyan OSSCube Solutions Pvt. Ltd.
Unit Test  Unit : The smallest testable part of an application.  Unit testing : Testing a unit of code isolated from its dependencies.  Testing with PHPUnit : The difference is between testing, that is, checking that your program behaves as expected, and performing a battery of tests, runnable code-fragments that automatically test the correctness of parts (units) of the software.
PHPUnit  Part of xUnit family(JUnit, Sunit,...)  Created by Sebastian Bergmann  Integrated in most IDE  Eclipse, Netbeans, Zend Stuide, PHPStorm  Integrated/supported  Zend Studio, Zend Framework, Cake, Symfony
PHPUnit's Goals  Tests should be:  Easy to learn to write.  Easy to write.  Easy to read.  Easy to execute.  Quick to execute.  Isolated.  Composable.  Resolve conflicts:  Easy to learn to write versus easy to write.  Isolated versus quick to execute.
Installing PHPUnit  PHPUnit is installed using the PEAR Installer  Commands to install :  pear config-set auto_discover 1  pear install pear.phpunit.de/PHPUnit
Writing Tests for PHPUnit  The tests for a class Class go into a class ClassTest.  ClassTest inherits (most of the time) from PHPUnit_Framework_TestCase.  The tests are public methods that are named test*.  Inside the test methods, assertion methods such as assertEquals() are used to assert that an actual value matches an expected value.
/Filename : user.php ?php Sample PHP class for testing lass User { protected $name; public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } public function talk() { return "Hello world!";
Test class for testing user.php ?php equire_once "PHPUnit/Autoload.php"; equire_once "user.php"; lass UserTest extends PHPUnit_Framework_TestCase
?php Test class for testing user.php .. lass UserTest extends PHPUnit_Framework_TestCase // test the talk method public function testTalk() { // make an instance of the user $user = new User(); // use assertEquals to ensure the greeting is what you expect $expected = "Hello world!"; $actual = $user->talk(); $this->assertEquals($expected, $actual);
The Command-Line Test Runner  The PHPUnit command-line test runner can be invoked through the phpunit command. phpunit UnitTest UnitTest.php Runs the tests that are provided by the class UnitTest. This class is expected to be declared in the specified sourcefile.
Running our Tests oot@varuntaliyan:/var/www/test-1# phpunit userTest.php HPUnit 3.6.10 by Sebastian Bergmann. ime: 0 seconds, Memory: 2.75Mb K (1 test, 1 assertion)
For each test run, the PHPUnit command-line tool prints one character to indicate progress:  . – Printed when a test succeeds.  F – Printed when an assertion fails.  E – Printed when an error occurs while running the test.  S – Printed when the test has been skipped.  I – Printed when the test is marked as being incomplete.
Output when a Test fails oot@varuntaliyan:/var/www/test-1# phpunit userTest.php HPUnit 3.6.10 by Sebastian Bergmann. ime: 0 seconds, Memory: 2.75Mb here was 1 failure: ) UserTest::testTalk ailed asserting that two strings are equal. -- Expected ++ Actual @ @@ 'Hello world!' 'Non sense' var/www/test-1/userTest.php:14
Test Dependencies PHPUnit supports the declaration of explicit dependencies between test methods. Such dependencies do not define the order in which the test methods are to be executed but they allow the returning of an instance of the test fixture by a producer and passing it to the dependent consumers. A producer is a test method that yields its unit under test as return value. A consumer is a test method that depends on one or more producers and their return values.
lass StackTest extends PHPUnit_Framework_TestCase public function testEmpty() Using the @depends annotation to express dependencies { $stack = array(); $this->assertEmpty($stack); return $stack; } /** * @depends testEmpty */ public function testPush(array $stack) { array_push($stack, 'foo'); $this->assertEquals('foo', $stack[count($stack)-1]); $this->assertNotEmpty($stack); return $stack; } /** * @depends testPush */ public function testPop(array $stack) {
Running the Test /var/www/test-1# phroot@varuntaliyanpunit depend.php HPUnit 3.6.10 by Sebastian Bergmann. .. ime: 0 seconds, Memory: 2.75Mb K (3 tests, 5 assertions)
Data Providers test method can accept arbitrary argumeants. These arguments are to be provided by a data provider methods.
lass DataTest extends PHPUnit_Framework_TestCase Using a data provider that returns an array of arrays /** * @dataProvider provider */ public function testAdd($a, $b, $c) { $this->assertEquals($c, $a + $b); } public function provider() { return array( array(0, 0, 0), array(0, 1, 1), array(1, 0, 1), array(1, 1, 3)
Testing Exceptions : Tests whether an exception is /Filename : exceptionclass.php ?php thrown inside the tested code. ni_set('display_errors', 1); lass myexcepclass extends Exception { unction checkNum($number) { if($number>1) { throw new Exception("Value must be 1 or below"); } return true;
?php Test class for exceptionclass.php equire_once '/usr/share/php/PHPUnit/Framework/TestCase.php'; equire_once 'exceptionclass.php'; lass myexcepclassTest extends PHPUnit_Framework_TestCase { ** * @expectedException InvalidArgumentException: */ public function testcheckNum() { $obj = new MyCustomException; $obj->checkNum(2); }
Running the test HPUnit 3.6.10 by Sebasroot@varuntaliyan:/var/www/tests/error# phpunit testexceptionclass.php ian Bergmann. ime: 0 seconds, Memory: 2.75Mb here was 1 failure: ) myexcepclassTest::testcheckNum ailed asserting that exception of type "Exception" matches expected exception "InvalidArgumentException:". AILURES!
Testing Output : Sometimes you want to assert that the execution of a method, for instance, generates an expected /Filename : outputclass.php output ?php ni_set('display_errors', 1); lass Myoutputclass { unction greetings() { print 'Hello Everyone'; } unction quote() { print 'Its morning again'; }
/Filename : testoutputclass.php ?php Test class for outputclass.php equire_once '/usr/share/php/PHPUnit/Framework/TestCase.php'; equire_once 'outputclass.php'; lass outputclassTest extends PHPUnit_Framework_TestCase protected $obj; protected function setUp() { $this->obj = new Myoutputclass; } public function testgreetings() { $this->expectOutputString('Hello Everyone'); $this->obj->greetings(); } public function testquote() { $this->expectOutputString('Its noon'); $this->obj->quote();
Running the test oot@varuntaliyan:/var/www/tests/output# phpunit testoutputclass.php HPUnit 3.6.10 by Sebastian Bergmann. F ime: 0 seconds, Memory: 2.75Mb here was 1 failure: ) outputclassTest::testquote ailed asserting that two strings are equal. -- Expected ++ Actual @ @@ 'Its noon' 'Its morning again' AILURES!
Assertions  assertArrayHasKey()  assertContains()  assertContainsOnly()  assertCount()  assertEmpty()  assertEquals()  assertFalse()  assertClassHasAttribute()  assertClassHasStaticAttribute().....
 assertGreaterThan()  assertGreaterThanOrEqual()  assertInstanceOf()  assertInternalType()  assertLessThan()  assertLessThanOrEqual()  assertNull()  assertRegExp()  assertSame()  assertStringEndsWith()  assertStringStartsWith()......
Fixtures  is a “known state” of an application  need to be “set up” at the start of test  need to be “torn down” at the end of the test  shares “states” over test methods  setUp() is where you create the objects against which you will test.  tearDown() is where you clean up the objects against which you tested.  More setUp() than tearDown()
Using setUp() to create the stack fixture <?php class StackTest extends PHPUnit_Framework_TestCase { protected $stack; protected function setUp() { $this->stack = array(); } public function testEmpty() { $this->assertTrue(empty($this->stack)); } public function testPush() { array_push($this->stack, 'foo'); $this->assertEquals('foo', $this->stack[count($this->stack)-1]); $this->assertFalse(empty($this->stack)); } public function testPop() { array_push($this->stack, 'foo'); $this->assertEquals('foo', array_pop($this->stack)); $this->assertTrue(empty($this->stack)); } } ?>
PHPUnit – Database Extension  PHPUnit Database Extension – DBUnit Port  Can be installed by : pear install phpunit/DbUnit  Currently supported databases:  MySQL  PostgreSQL  Oracle  SQLite  has access to other database systems such as IBM DB2 or Microsoft SQL Server Through Zend Framework or Doctrine 2 integrations
The four stages of a database test 1.Set up fixture 2.Exercise System Under Test 3.Verify outcome 4.Teardown
Configuration of a PHPUnit Database TestCase  Need to Extend abstract TestCase : PHPUnit_Extensions_Database_TestCase require_once 'PHPUnit/Extensions/Database/TestCase.php'; class BankAccountDBTest extends PHPUnit_Extensions_Database_TestCase { }
Configuration of a PHPUnit Database TestCase  Must Implement getConnection() - Returns a database connection wrapper. getDataSet() - Returns the dataset to seed the database with.
Implementation of getConnection() and getDataset() methods ?php require_once 'PHPUnit/Extensions/Database/TestCase.php'; class DatabaseTest extends PHPUnit_Extensions_Database_TestCase { protected function getConnection() { $pdo = new PDO('mysql:host=localhost;dbname=testdb', 'root', ''); return $this->createDefaultDBConnection($pdo, 'testdb'); } protected function getDataSet() { return $this->createFlatXMLDataSet(dirname(__FILE__).'/_files/bank- account-seed.xml'); } } ?>
Test class for database testing /Filename : dbclass.php ?php lass BankAccount { ublic function __construct($accno, $conn, $bal=0) { this->addData(array($accno,$bal),$conn); unction addData($data, $conn) { sql = "INSERT INTO bank_account (account_number, balance) VALUES (:acc,:bal)"; q = $conn->prepare($sql); q->execute(array(':acc'=>$data[0],
Test case for dbclass.php ?php equire_once 'PHPUnit/Extensions/Database/TestCase.php'; equire_once "dbclass.php"; lass BankAccountDBTest extends PHPUnit_Extensions_Database_TestCase protected $pdo; public function __construct() { $this->pdo = new PDO('mysql:host=localhost;dbname=phpunitdb', 'root', 'root'); } protected function getConnection() { return $this->createDefaultDBConnection($this->pdo, 'phpunitdb'); } protected function getDataSet() { return $this->createFlatXMLDataSet('/var/www/tests/bankaccdb/files/seed.xml'); } public function testaddData()
Running the test oot@varuntaliyan:/var/www/tests/bank accdb# phpunit dbclasstest.php HPUnit 3.6.10 by Sebastian Bergmann. ime: 0 seconds, Memory: 3.00Mb
Output when a Test fails oot@varuntaliyan:/var/www/tests/bankaccdb# phpunit dbclasstest.php HPUnit 3.6.10 by Sebastian Bergmann. ime: 0 seconds, Memory: 3.00Mb here was 1 failure: ) BankAccountDBTest::testaddData ailed asserting that ----------------------+----------------------+ bank_account | ----------------------+----------------------+ account_number | balance | ----------------------+----------------------+ 1593490 | 100 | ----------------------+----------------------+ 1593648 | 1216 |
+----------------------+----------------------+ | bank_account | +----------------------+----------------------+ | account_number | balance | +----------------------+----------------------+ | 1593490 | 100.00 | +----------------------+----------------------+ | 1593648 | 1216.00 | +----------------------+----------------------+ | 1234861 | 89.00 | +----------------------+----------------------+ | 1593648 | 1216.00 | +----------------------+----------------------+ /var/www/tests/bankaccdb/dbclasstest.php:29 FAILURES! Tests: 1, Assertions: 1, Failures: 1.
Thank you - Resources  http:// www.phpunit.de/manual/3.6/en/index.html  http://www.ds-o.com/archives/63- PHPUnit-Database-Extension-DBUnit- Port.html

Unit Testing using PHPUnit

  • 1.
    PHPUnit Automated Unit TestingFramework. By : Varun Taliyan OSSCube Solutions Pvt. Ltd.
  • 2.
    Unit Test  Unit : The smallest testable part of an application.  Unit testing : Testing a unit of code isolated from its dependencies.  Testing with PHPUnit : The difference is between testing, that is, checking that your program behaves as expected, and performing a battery of tests, runnable code-fragments that automatically test the correctness of parts (units) of the software.
  • 3.
    PHPUnit  Part of xUnit family(JUnit, Sunit,...)  Created by Sebastian Bergmann  Integrated in most IDE  Eclipse, Netbeans, Zend Stuide, PHPStorm  Integrated/supported  Zend Studio, Zend Framework, Cake, Symfony
  • 4.
    PHPUnit's Goals  Tests should be:  Easy to learn to write.  Easy to write.  Easy to read.  Easy to execute.  Quick to execute.  Isolated.  Composable.  Resolve conflicts:  Easy to learn to write versus easy to write.  Isolated versus quick to execute.
  • 5.
    Installing PHPUnit  PHPUnit is installed using the PEAR Installer  Commands to install :  pear config-set auto_discover 1  pear install pear.phpunit.de/PHPUnit
  • 6.
    Writing Tests forPHPUnit  The tests for a class Class go into a class ClassTest.  ClassTest inherits (most of the time) from PHPUnit_Framework_TestCase.  The tests are public methods that are named test*.  Inside the test methods, assertion methods such as assertEquals() are used to assert that an actual value matches an expected value.
  • 7.
    /Filename : user.php ?php Sample PHP class for testing lass User { protected $name; public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } public function talk() { return "Hello world!";
  • 8.
    Test class fortesting user.php ?php equire_once "PHPUnit/Autoload.php"; equire_once "user.php"; lass UserTest extends PHPUnit_Framework_TestCase
  • 9.
    ?php Test class for testing user.php .. lass UserTest extends PHPUnit_Framework_TestCase // test the talk method public function testTalk() { // make an instance of the user $user = new User(); // use assertEquals to ensure the greeting is what you expect $expected = "Hello world!"; $actual = $user->talk(); $this->assertEquals($expected, $actual);
  • 10.
    The Command-Line TestRunner  The PHPUnit command-line test runner can be invoked through the phpunit command. phpunit UnitTest UnitTest.php Runs the tests that are provided by the class UnitTest. This class is expected to be declared in the specified sourcefile.
  • 11.
    Running our Tests oot@varuntaliyan:/var/www/test-1#phpunit userTest.php HPUnit 3.6.10 by Sebastian Bergmann. ime: 0 seconds, Memory: 2.75Mb K (1 test, 1 assertion)
  • 12.
    For each testrun, the PHPUnit command-line tool prints one character to indicate progress:  . – Printed when a test succeeds.  F – Printed when an assertion fails.  E – Printed when an error occurs while running the test.  S – Printed when the test has been skipped.  I – Printed when the test is marked as being incomplete.
  • 13.
    Output when aTest fails oot@varuntaliyan:/var/www/test-1# phpunit userTest.php HPUnit 3.6.10 by Sebastian Bergmann. ime: 0 seconds, Memory: 2.75Mb here was 1 failure: ) UserTest::testTalk ailed asserting that two strings are equal. -- Expected ++ Actual @ @@ 'Hello world!' 'Non sense' var/www/test-1/userTest.php:14
  • 14.
    Test Dependencies PHPUnit supports the declaration of explicit dependencies between test methods. Such dependencies do not define the order in which the test methods are to be executed but they allow the returning of an instance of the test fixture by a producer and passing it to the dependent consumers. A producer is a test method that yields its unit under test as return value. A consumer is a test method that depends on one or more producers and their return values.
  • 15.
    lass StackTest extendsPHPUnit_Framework_TestCase public function testEmpty() Using the @depends annotation to express dependencies { $stack = array(); $this->assertEmpty($stack); return $stack; } /** * @depends testEmpty */ public function testPush(array $stack) { array_push($stack, 'foo'); $this->assertEquals('foo', $stack[count($stack)-1]); $this->assertNotEmpty($stack); return $stack; } /** * @depends testPush */ public function testPop(array $stack) {
  • 16.
    Running the Test /var/www/test-1#phroot@varuntaliyanpunit depend.php HPUnit 3.6.10 by Sebastian Bergmann. .. ime: 0 seconds, Memory: 2.75Mb K (3 tests, 5 assertions)
  • 17.
    Data Providers test methodcan accept arbitrary argumeants. These arguments are to be provided by a data provider methods.
  • 18.
    lass DataTest extendsPHPUnit_Framework_TestCase Using a data provider that returns an array of arrays /** * @dataProvider provider */ public function testAdd($a, $b, $c) { $this->assertEquals($c, $a + $b); } public function provider() { return array( array(0, 0, 0), array(0, 1, 1), array(1, 0, 1), array(1, 1, 3)
  • 19.
    Testing Exceptions :Tests whether an exception is /Filename : exceptionclass.php ?php thrown inside the tested code. ni_set('display_errors', 1); lass myexcepclass extends Exception { unction checkNum($number) { if($number>1) { throw new Exception("Value must be 1 or below"); } return true;
  • 20.
    ?php Test class forexceptionclass.php equire_once '/usr/share/php/PHPUnit/Framework/TestCase.php'; equire_once 'exceptionclass.php'; lass myexcepclassTest extends PHPUnit_Framework_TestCase { ** * @expectedException InvalidArgumentException: */ public function testcheckNum() { $obj = new MyCustomException; $obj->checkNum(2); }
  • 21.
    Running the test HPUnit3.6.10 by Sebasroot@varuntaliyan:/var/www/tests/error# phpunit testexceptionclass.php ian Bergmann. ime: 0 seconds, Memory: 2.75Mb here was 1 failure: ) myexcepclassTest::testcheckNum ailed asserting that exception of type "Exception" matches expected exception "InvalidArgumentException:". AILURES!
  • 22.
    Testing Output : Sometimes you want to assert that the execution of a method, for instance, generates an expected /Filename : outputclass.php output ?php ni_set('display_errors', 1); lass Myoutputclass { unction greetings() { print 'Hello Everyone'; } unction quote() { print 'Its morning again'; }
  • 23.
    /Filename : testoutputclass.php ?php Test class for outputclass.php equire_once '/usr/share/php/PHPUnit/Framework/TestCase.php'; equire_once 'outputclass.php'; lass outputclassTest extends PHPUnit_Framework_TestCase protected $obj; protected function setUp() { $this->obj = new Myoutputclass; } public function testgreetings() { $this->expectOutputString('Hello Everyone'); $this->obj->greetings(); } public function testquote() { $this->expectOutputString('Its noon'); $this->obj->quote();
  • 24.
    Running the test oot@varuntaliyan:/var/www/tests/output#phpunit testoutputclass.php HPUnit 3.6.10 by Sebastian Bergmann. F ime: 0 seconds, Memory: 2.75Mb here was 1 failure: ) outputclassTest::testquote ailed asserting that two strings are equal. -- Expected ++ Actual @ @@ 'Its noon' 'Its morning again' AILURES!
  • 25.
    Assertions  assertArrayHasKey()  assertContains()  assertContainsOnly()  assertCount()  assertEmpty()  assertEquals()  assertFalse()  assertClassHasAttribute()  assertClassHasStaticAttribute().....
  • 26.
    assertGreaterThan()  assertGreaterThanOrEqual()  assertInstanceOf()  assertInternalType()  assertLessThan()  assertLessThanOrEqual()  assertNull()  assertRegExp()  assertSame()  assertStringEndsWith()  assertStringStartsWith()......
  • 27.
    Fixtures  is a “known state” of an application  need to be “set up” at the start of test  need to be “torn down” at the end of the test  shares “states” over test methods  setUp() is where you create the objects against which you will test.  tearDown() is where you clean up the objects against which you tested.  More setUp() than tearDown()
  • 28.
    Using setUp() tocreate the stack fixture <?php class StackTest extends PHPUnit_Framework_TestCase { protected $stack; protected function setUp() { $this->stack = array(); } public function testEmpty() { $this->assertTrue(empty($this->stack)); } public function testPush() { array_push($this->stack, 'foo'); $this->assertEquals('foo', $this->stack[count($this->stack)-1]); $this->assertFalse(empty($this->stack)); } public function testPop() { array_push($this->stack, 'foo'); $this->assertEquals('foo', array_pop($this->stack)); $this->assertTrue(empty($this->stack)); } } ?>
  • 29.
    PHPUnit – DatabaseExtension  PHPUnit Database Extension – DBUnit Port  Can be installed by : pear install phpunit/DbUnit  Currently supported databases:  MySQL  PostgreSQL  Oracle  SQLite  has access to other database systems such as IBM DB2 or Microsoft SQL Server Through Zend Framework or Doctrine 2 integrations
  • 30.
    The four stagesof a database test 1.Set up fixture 2.Exercise System Under Test 3.Verify outcome 4.Teardown
  • 31.
    Configuration of aPHPUnit Database TestCase  Need to Extend abstract TestCase : PHPUnit_Extensions_Database_TestCase require_once 'PHPUnit/Extensions/Database/TestCase.php'; class BankAccountDBTest extends PHPUnit_Extensions_Database_TestCase { }
  • 32.
    Configuration of aPHPUnit Database TestCase  Must Implement getConnection() - Returns a database connection wrapper. getDataSet() - Returns the dataset to seed the database with.
  • 33.
    Implementation of getConnection()and getDataset() methods ?php require_once 'PHPUnit/Extensions/Database/TestCase.php'; class DatabaseTest extends PHPUnit_Extensions_Database_TestCase { protected function getConnection() { $pdo = new PDO('mysql:host=localhost;dbname=testdb', 'root', ''); return $this->createDefaultDBConnection($pdo, 'testdb'); } protected function getDataSet() { return $this->createFlatXMLDataSet(dirname(__FILE__).'/_files/bank- account-seed.xml'); } } ?>
  • 34.
    Test class fordatabase testing /Filename : dbclass.php ?php lass BankAccount { ublic function __construct($accno, $conn, $bal=0) { this->addData(array($accno,$bal),$conn); unction addData($data, $conn) { sql = "INSERT INTO bank_account (account_number, balance) VALUES (:acc,:bal)"; q = $conn->prepare($sql); q->execute(array(':acc'=>$data[0],
  • 35.
    Test case fordbclass.php ?php equire_once 'PHPUnit/Extensions/Database/TestCase.php'; equire_once "dbclass.php"; lass BankAccountDBTest extends PHPUnit_Extensions_Database_TestCase protected $pdo; public function __construct() { $this->pdo = new PDO('mysql:host=localhost;dbname=phpunitdb', 'root', 'root'); } protected function getConnection() { return $this->createDefaultDBConnection($this->pdo, 'phpunitdb'); } protected function getDataSet() { return $this->createFlatXMLDataSet('/var/www/tests/bankaccdb/files/seed.xml'); } public function testaddData()
  • 36.
    Running the test oot@varuntaliyan:/var/www/tests/bank accdb#phpunit dbclasstest.php HPUnit 3.6.10 by Sebastian Bergmann. ime: 0 seconds, Memory: 3.00Mb
  • 37.
    Output when aTest fails oot@varuntaliyan:/var/www/tests/bankaccdb# phpunit dbclasstest.php HPUnit 3.6.10 by Sebastian Bergmann. ime: 0 seconds, Memory: 3.00Mb here was 1 failure: ) BankAccountDBTest::testaddData ailed asserting that ----------------------+----------------------+ bank_account | ----------------------+----------------------+ account_number | balance | ----------------------+----------------------+ 1593490 | 100 | ----------------------+----------------------+ 1593648 | 1216 |
  • 38.
    +----------------------+----------------------+ | bank_account | +----------------------+----------------------+ | account_number | balance | +----------------------+----------------------+ | 1593490 | 100.00 | +----------------------+----------------------+ | 1593648 | 1216.00 | +----------------------+----------------------+ | 1234861 | 89.00 | +----------------------+----------------------+ | 1593648 | 1216.00 | +----------------------+----------------------+ /var/www/tests/bankaccdb/dbclasstest.php:29 FAILURES! Tests: 1, Assertions: 1, Failures: 1.
  • 39.
    Thank you -Resources  http:// www.phpunit.de/manual/3.6/en/index.html  http://www.ds-o.com/archives/63- PHPUnit-Database-Extension-DBUnit- Port.html