Unit Testing using PHPUnit

39
PHPUnit Automated Unit Testing Framework. By : Varun Taliyan OSSCube Solutions Pvt. Ltd.

Transcript of Unit Testing using PHPUnit

Page 1: Unit Testing using  PHPUnit

PHPUnitAutomated Unit Testing Framework.

By : Varun TaliyanOSSCube Solutions Pvt. Ltd.

Page 2: Unit Testing using  PHPUnit

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.

Page 3: Unit Testing using  PHPUnit

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

Page 4: Unit Testing using  PHPUnit

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.

Page 5: Unit Testing using  PHPUnit

Installing PHPUnit PHPUnit is installed using the PEAR

Installer Commands to install :

pear config-set auto_discover 1 pear install pear.phpunit.de/PHPUnit

Page 6: Unit Testing using  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.

Page 7: Unit Testing using  PHPUnit

Sample PHP class for testing//Filename : user.php<?phpclass User { protected $name; public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } public function talk() { return "Hello world!"; }}?>

Page 8: Unit Testing using  PHPUnit

Test class for testing user.php

<?phprequire_once "PHPUnit/Autoload.php";require_once "user.php";

class UserTest extends PHPUnit_Framework_TestCase{}?>

Page 9: Unit Testing using  PHPUnit

Test class for testing user.php

<?php...class 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); }}

Page 10: Unit Testing using  PHPUnit

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.

Page 11: Unit Testing using  PHPUnit

Running our Tests

root@varuntaliyan:/var/www/test-1# phpunit userTest.phpPHPUnit 3.6.10 by Sebastian Bergmann..

Time: 0 seconds, Memory: 2.75Mb

OK (1 test, 1 assertion)

Page 12: Unit Testing using  PHPUnit

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.

Page 13: Unit Testing using  PHPUnit

Output when a Test fails

root@varuntaliyan:/var/www/test-1# phpunit userTest.php

PHPUnit 3.6.10 by Sebastian Bergmann.

FaTime: 0 seconds, Memory: 2.75Mb

There was 1 failure:

1) UserTest::testTalkFailed asserting that two strings are equal.--- Expected+++ Actual@@ @@-'Hello world!'+'Non sense'

/var/www/test-1/userTest.php:14

FAILURES!Tests: 1, Assertions: 1, Failures: 1.

Page 14: Unit Testing using  PHPUnit

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.

Page 15: Unit Testing using  PHPUnit

Using the @depends annotation to express dependencies

<?phpclass StackTest extends PHPUnit_Framework_TestCase{ public function testEmpty() { $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) { $this->assertEquals('foo', array_pop($stack)); $this->assertEmpty($stack); }}?>

Page 16: Unit Testing using  PHPUnit

Running the Test

:/var/www/test-1# phroot@varuntaliyanpunit depend.php PHPUnit 3.6.10 by Sebastian Bergmann.

...

Time: 0 seconds, Memory: 2.75Mb

OK (3 tests, 5 assertions)

Page 17: Unit Testing using  PHPUnit

Data Providers

A test method can accept arbitrary argumeants. These arguments are to be provided by a data provider methods.

Page 18: Unit Testing using  PHPUnit

Using a data provider that returns an array of arrays

<?phpclass DataTest extends PHPUnit_Framework_TestCase{ /** * @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) ); }}?>

Page 19: Unit Testing using  PHPUnit

Testing Exceptions : Tests whether an exception is

thrown inside the tested code.

//Filename : exceptionclass.php<?phpini_set('display_errors', 1);class myexcepclass extends Exception {function checkNum($number) { if($number>1) { throw new Exception("Value must be 1 or below"); } return true; }}?>

Page 20: Unit Testing using  PHPUnit

Test class for exceptionclass.php

<?phprequire_once '/usr/share/php/PHPUnit/Framework/TestCase.php';require_once 'exceptionclass.php';class myexcepclassTest extends PHPUnit_Framework_TestCase {/** * @expectedException InvalidArgumentException: */

public function testcheckNum() {$obj = new MyCustomException;$obj->checkNum(2);

}}?>

Page 21: Unit Testing using  PHPUnit

Running the test PHPUnit 3.6.10 by Sebasroot@varuntaliyan:/var/www/tests/error# phpunit testexceptionclass.php tian Bergmann.FTime: 0 seconds, Memory: 2.75Mb

There was 1 failure:

1) myexcepclassTest::testcheckNumFailed asserting that exception of type "Exception" matches expected exception "InvalidArgumentException:".

FAILURES!Tests: 1, Assertions: 1, Failures: 1.

Page 22: Unit Testing using  PHPUnit

Testing Output : Sometimes you want to assert that the execution of a method, for instance, generates an expected output

//Filename : outputclass.php<?phpini_set('display_errors', 1);class Myoutputclass {function greetings() {

print 'Hello Everyone'; }function quote() {

print 'Its morning again'; }}?>

Page 23: Unit Testing using  PHPUnit

Test class for outputclass.php

//Filename : testoutputclass.php<?phprequire_once '/usr/share/php/PHPUnit/Framework/TestCase.php';require_once 'outputclass.php';

class 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(); } }?>

Page 24: Unit Testing using  PHPUnit

Running the test

root@varuntaliyan:/var/www/tests/output# phpunit testoutputclass.php PHPUnit 3.6.10 by Sebastian Bergmann.

.F

Time: 0 seconds, Memory: 2.75Mb

There was 1 failure:

1) outputclassTest::testquoteFailed asserting that two strings are equal.--- Expected+++ Actual@@ @@-'Its noon'+'Its morning again'

FAILURES!Tests: 2, Assertions: 2, Failures: 1.

Page 25: Unit Testing using  PHPUnit

Assertions assertArrayHasKey() assertContains() assertContainsOnly() assertCount() assertEmpty() assertEquals() assertFalse() assertClassHasAttribute() assertClassHasStaticAttribute().....

Page 26: Unit Testing using  PHPUnit

assertGreaterThan()

assertGreaterThanOrEqual()

assertInstanceOf()

assertInternalType()

assertLessThan()

assertLessThanOrEqual()

assertNull()

assertRegExp()

assertSame()

assertStringEndsWith()

assertStringStartsWith()......

Page 27: Unit Testing using  PHPUnit

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()

Page 28: Unit Testing using  PHPUnit

Using setUp() to create the stack fixture<?phpclass 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)); }}?>

Page 29: Unit Testing using  PHPUnit

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

Page 30: Unit Testing using  PHPUnit

The four stages of a database test

1.Set up fixture2.Exercise System Under Test3.Verify outcome4.Teardown

Page 31: Unit Testing using  PHPUnit

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

{}

Page 32: Unit Testing using  PHPUnit

Configuration of a PHPUnit Database TestCase

Must Implement getConnection() - Returns a database

connection wrapper.getDataSet() - Returns the dataset to seed

the database with.

Page 33: Unit Testing using  PHPUnit

Implementation of getConnection() and getDataset() methods

<?phprequire_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'); }}?>

Page 34: Unit Testing using  PHPUnit

Test class for database testing//Filename : dbclass.php<?phpclass BankAccount {public function __construct($accno, $conn, $bal=0) {$this->addData(array($accno,$bal),$conn);}function addData($data, $conn) {$sql = "INSERT INTO bank_account (account_number, balance) VALUES (:acc,:bal)";$q = $conn->prepare($sql);$q->execute(array(':acc'=>$data[0], ':bal'=>$data[1]));}}

Page 35: Unit Testing using  PHPUnit

Test case for dbclass.php <?phprequire_once 'PHPUnit/Extensions/Database/TestCase.php';require_once "dbclass.php";class 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() { $bank_account = new BankAccount('1234567', $this->pdo); $xml_dataset = $this->createFlatXMLDataSet('/var/www/tests/bankaccdb/files/seed-after-insert.xml'); $this->assertTablesEqual($xml_dataset->getTable('bank_account'),$this->getConnection()->createDataSet()->getTable('bank_account')); }}

Page 36: Unit Testing using  PHPUnit

Running the test root@varuntaliyan:/var/www/tests/bankaccdb# phpunit dbclasstest.php PHPUnit 3.6.10 by Sebastian Bergmann..Time: 0 seconds, Memory: 3.00Mb

OK (1 test, 1 assertion)

Page 37: Unit Testing using  PHPUnit

Output when a Test failsroot@varuntaliyan:/var/www/tests/bankaccdb# phpunit dbclasstest.php PHPUnit 3.6.10 by Sebastian Bergmann.FTime: 0 seconds, Memory: 3.00MbThere was 1 failure:1) BankAccountDBTest::testaddDataFailed asserting that +----------------------+----------------------+| bank_account |+----------------------+----------------------+| account_number | balance |+----------------------+----------------------+| 1593490 | 100 |+----------------------+----------------------+| 1593648 | 1216 |+----------------------+----------------------+| 1234861 | 89 |+----------------------+----------------------+| 1593648 | 1216 |+----------------------+----------------------+| 1234567 | 0 |+----------------------+----------------------+

is equal to expected

Page 38: Unit Testing using  PHPUnit

+----------------------+----------------------+

| 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.

Page 39: Unit Testing using  PHPUnit

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