Introduction to Unit Testing with PHPUnit
Upcoming SlideShare
Loading in...5
×
 

Introduction to Unit Testing with PHPUnit

on

  • 30,532 views

Introduction to Unit Testing with PHPUnit, added with the Zend Framework Test component.

Introduction to Unit Testing with PHPUnit, added with the Zend Framework Test component.

Statistics

Views

Total Views
30,532
Views on SlideShare
30,308
Embed Views
224

Actions

Likes
23
Downloads
552
Comments
3

15 Embeds 224

http://www.slideshare.net 101
http://navegarepressiso.blogspot.com.br 62
http://navegarepressiso.blogspot.com 26
http://www.askqtp.com 10
http://askqtp.blogspot.com 8
http://www.linkedin.com 4
http://paper.li 3
http://localhost 2
http://translate.googleusercontent.com 2
http://www.health.medicbd.com 1
http://a0.twimg.com 1
http://localhost:8080 1
http://navegarepressiso.blogspot.de 1
http://navegarepressiso.blogspot.com.es 1
http://pulse.plaxo.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

13 of 3 Post a comment

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • how to install pear without zend framework or i can use another framework?
    Are you sure you want to
    Your message goes here
    Processing…
  • Also can u explain me some queries related to Database implementation class

    1. What is the state Database when we are testing this class
    Do the table contains the three record at the time of testing?
    Does the XML 'BankAccount.xml' and 'NewBankAccount.xml' are genrated dynamically ?
    Also what is the state of both the files before testing?

    Also when i test i do no get any new data inserted in DB
    Are you sure you want to
    Your message goes here
    Processing…
  • Is it necessary to extend class with PPUnit_Extensions_Database_TestCase ?

    Can i get an example Without extending it ?
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Introduction to Unit Testing with PHPUnit Introduction to Unit Testing with PHPUnit Presentation Transcript

    • Introduction to Unit Testing with PHPUnit by Michelangelo van Dam
    • Contents ✓Who am I ? ✓Expected Exceptions ✓What is Unit ✓Fixtures Testing ? ✓Doubles ✓Unit Testing in short ✓Stubs ✓Why do Testing ? ✓Mocks ✓SimpleTest ✓Database Testing ✓PHPUnit ✓Zend_Test ✓Starting w/ PHPUnit ✓Interesting Readings ✓Example ✓Questions ? ✓More Testing ✓Data Provider 2
    • Who am I ? Michelangelo van Dam Independent Enterprise PHP consultant Co-founder PHPBelgium Mail me at dragonbe [at] gmail [dot] com Follow me on http://twitter.com/DragonBe Read my articles on http://dragonbe.com See my profile on http://linkedin.com/in/michelangelovandam 3
    • What is Unit Testing ? Wikipedia: “is a method of testing that verifies the individual units of source code are working properly” 4
    • Unit Testing in short • unit: the smallest testable code of an app - procedural: function or procedure - OOP: a method • test: code that checks code on - functional behavior ✓ expected results ✓ unexpected failures 5
    • Why do (Unit) Testing ? • automated testing • test code on functionality • detect issues that break existing code • progress indication of the project • alerts generation for monitoring tools 6
    • SimpleTest • comparable to JUnit/PHPUnit • created by Marcus Baker • popular for testing web pages at browser level 7
    • PHPUnit • Part of xUnit familiy (JUnit, SUnit,...) • created by Sebastian Bergmann • integrated/supported - Zend Studio - Zend Framework 8
    • Starting with PHPUnit Installation is done with the PEAR installer # pear channel-discover pear.phpunit.de # pear install phpunit/PHPUnit Upgrading is as simple # pear upgrade phpunit/PHPUnit 9
    • Hello World <?php class HelloWorld { public $helloWorld; public function __construct($string = ‘Hello World!’) { $this->helloWorld = $string; } public function sayHello() { return $this->helloWorld; } } 10
    • <?php Test HelloWorld class require_once 'HelloWorld.php'; require_once 'PHPUnit/Framework.php'; class HelloWorldTest extends PHPUnit_Framework_TestCase { public function test__construct() { $hw = new HelloWorld(); $this->assertType('HelloWorld', $hw); } public function testSayHello() { $hw = new HelloWorld(); $string = $hw->sayHello(); $this->assertEquals('Hello World!', $string); } } 11
    • Testing HelloWorld # phpunit HelloWorldTest HelloWorldTest.php PHPUnit 3.3.2 by Sebastian Bergmann. .. Time: 0 seconds OK (2 tests, 2 assertions) 12
    • More testing • data providers (@dataProvider) • exception (@expectedException) • fixtures (setUp() and tearDown()) • doubles (mocks and stubs) • database testing 13
    • Data Provider • provides arbitrary arguments - array - object (that implements Iterator) • annotated by @dataProvider provider • multiple arguments 14
    • CombineTest <?php class CombineTest extends PHPUnit_Framework_TestCase { /** * @dataProvider provider */ public function testCombine($a, $b, $c) { $this->assertEquals($c, $a . ' ' . $b); } public function provider() { return array ( array ('Hello','World','Hello World'), array ('Go','PHP','Go PHP'), array ('This','Fails','This succeeds') ); } } 15
    • Testing CombineTest # phpunit CombineTest CombineTest.php PHPUnit 3.3.2 by Sebastian Bergmann. ..F Time: 0 seconds There was 1 failure: 1) testCombine(CombineTest) with data set #2 ('This', 'Fails', 'This succeeds') Failed asserting that two strings are equal. expected string <This succeeds> difference < xxxxx???> got string <This Fails> /root/dev/phpunittutorial/CombineTest.php:9 FAILURES! Tests: 3, Assertions: 3, Failures: 1. 16
    • Expected Exception • testing exceptions - that they are thrown - are properly catched 17
    • OopsTest <?php class OopsTest extends PHPUnit_Framework_TestCase { public function testOops() { try { throw new Exception('I just made a booboo'); } catch (Exception $expected) { return; } $this->fail('An expected Exception was not thrown'); } } 18
    • Testing OopsTest # phpunit OopsTest OopsTest.php PHPUnit 3.3.2 by Sebastian Bergmann. . Time: 0 seconds OK (1 test, 0 assertions) 19
    • Fixtures • is a “known state” of an application - needs to be ‘set up’ at start of test - needs to be ‘torn down’ at end of test - shares “states” over test methods 20
    • FixmeTest <?php class FixmeTest extends PHPUnit_Framework_TestCase { protected $fixme; public function setUp() { $this->fixme = array (); } public function testFixmeEmpty() { $this->assertEquals(0, sizeof($this->fixme)); } public function testFixmeHasOne() { array_push($this->fixme, 'element'); $this->assertEquals(1, sizeof($this->fixme)); } } 21
    • Testing FixmeTest # phpunit FixmeTest FixmeTest.php PHPUnit 3.3.2 by Sebastian Bergmann. .. Time: 0 seconds OK (2 tests, 2 assertions) 22
    • Doubles • stub objects • mock objects 23
    • Stubs • isolates tests from external influences - slow connections - expensive and complex resources • replaces a “system under test” (SUT) - for the purpose of testing 24
    • StubTest <?php // example taken from phpunit.de class StubTest extends PHPUnit_Framework_TestCase { public function testStub() { $stub = $this->getMock('SomeClass'); $stub->expects($this->any()) ->method('doSometing') ->will($this->returnValue('foo')); } // Calling $stub->doSomething() will now return 'foo' } 25
    • Testing StubTest # phpunit StubTest StubTest.php PHPUnit 3.3.2 by Sebastian Bergmann. . Time: 0 seconds OK (1 test, 1 assertion) 26
    • Mocks • simulated objects • mimics API or behaviour • in a controlled way • to test a real object 27
    • ObserverTest <?php // example taken from Sebastian Bergmann’s slides on // slideshare.net/sebastian_bergmann/advanced-phpunit-topics class ObserverTest extends PHPUnit_Framework_TestCase { public function testUpdateIsCalledOnce() { $observer = $this->getMock('Observer', array('update')); $observer->expects($this->once()) ->method('update') ->with($this->equalTo('something')); $subject = new Subject; $subject->attach($observer) ->doSomething(); } } 28
    • Database Testing • Ported by Mike Lively from DBUnit • PHPUnit_Extensions_Database_TestCase • for database-driven projects • puts DB in know state between tests • imports and exports DB data from/to XML • easily added to existing tests 29
    • BankAccount Example BankAccount example by Mike Lively http://www.ds-o.com/archives/63-PHPUnit-Database-Extension-DBUnit-Port.html http://www.ds-o.com/archives/64-Adding-Database-Tests-to-Existing-PHPUnit-Test-Cases.html BankAccount class by Sebastian Bergmann http://www.slideshare.net/sebastian_bergmann/testing-phpweb-applications-with-phpunit-and-selenium The full BankAccount class http://www.phpunit.de/browser/phpunit/branches/release/3.3/PHPUnit/Samples/BankAccount/BankAccount.php 30
    • BankAccount <?php require_once 'BankAccountException.php'; class BankAccount { private $balance = 0; public function getBalance() { return $this->balance; } public function setBalance($balance) { if ($balance >= 0) { $this->balance = $balance; } else { throw new BankAccountException; } } ... 31
    • BankAccount (2) ... public function depositMoney($balance) { $this->setBalance($this->getBalance() + $balance); return $this->getBalance(); } public function withdrawMoney($balance) { $this->setBalance($this->getBalance() - $balance); return $this->getBalance(); } } <?php class BankAccountException extends RuntimeException { } 32
    • <?php BankAccountTest require_once 'PHPUnit/Extensions/Database/TestCase.php'; require_once 'BankAccount.php'; class BankAccountDBTest extends PHPUnit_Extensions_Database_TestCase { protected $pdo; public function __construct() { $this->pdo = new PDO('sqlite::memory:'); BankAccount::createTable($this->pdo); } protected function getConnection() { return $this->createDefaultDBConnection($this->pdo, 'sqlite'); } protected function getDataSet() { return $this->createFlatXMLDataSet( dirname(__FILE__) . '/BankAccounts.xml'); } ... 33
    • BankAccountTest (2) ... public function testNewAccountCreation() { $bank_account = new BankAccount('12345678912345678', $this->pdo); $xml_dataset = $this->createFlatXMLDataSet( dirname(__FILE__) . '/NewBankAccounts.xml'); $this->assertDataSetsEqual( $xml_dataset, $this->getConnection()->createDataSet() ); } } 34
    • Testing BankAccount # phpunit BankAccountDbTest BankAccountDbTest.php PHPUnit 3.3.2 by Sebastian Bergmann. F Time: 0 seconds There was 1 failure: ... 35
    • Testing BA (2) ... 1) testNewAccountCreation(BankAccountDBTest) Failed asserting that actual +----------------------+----------------------+ | bank_account | +----------------------+----------------------+ | account_number | balance | +----------------------+----------------------+ | 12345678912345678 | 0 | +----------------------+----------------------+ | 12348612357236185 | 89 | +----------------------+----------------------+ | 15934903649620486 | 100 | +----------------------+----------------------+ | 15936487230215067 | 1216 | +----------------------+----------------------+ 36
    • ... Testing BA (3) is equal to expected +----------------------+----------------------+ | bank_account | +----------------------+----------------------+ | account_number | balance | +----------------------+----------------------+ | 15934903649620486 | 100.00 | +----------------------+----------------------+ | 15936487230215067 | 1216.00 | +----------------------+----------------------+ | 12348612357236185 | 89.00 | +----------------------+----------------------+ Reason: Expected row count of 3, has a row count of 4 /root/dev/phpunittutorial/BankAccountDbTest.php:33 FAILURES! Tests: 1, Assertions: 1, Failures: 1. 37
    • BankAccount Dataset <!-- file: BankAccounts.xml --> <dataset> <bank_account account_number=quot;15934903649620486quot; balance=quot;100.00quot; /> <bank_account account_number=quot;15936487230215067quot; balance=quot;1216.00quot; /> <bank_account account_number=quot;12348612357236185quot; balance=quot;89.00quot; /> </dataset> 38
    • Testing MVC ZF apps • Available from Zend Framework 1.6 • Using Zend_Test http://framework.zend.com/manual/en/zend.test.html • Requests and Responses are mocked 39
    • Hints & Tips • Make sure auto loading is set up - your tests might fail on not finding classes • Move bootstrap to a plugin - allows to PHP callback the bootstrap - allows to specify environment succinctly - allows to bootstrap application in a 1 line 40
    • Defining the bootstrap /** * default way to approach the bootstrap */ class IndexControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { public $bootstrap = '/path/to/bootstrap.php'; // ... } /** * Using PHP callback */ class IndexControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { public $bootstrap = array('App', 'bootstrap'); // ... } 41
    • Testing homepage class IndexControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { // ... public function testHomePage() { $this->dispatch('/'); // ... } } 42
    • Testing GET params class IndexControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { // ... public function testGetActionShouldReceiveGetParams() { // Set GET variables: $this->request->setQuery(array( 'foo' => 'bar', 'bar' => 'baz', )); } // ... } 43
    • Testing POST params class IndexControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { // ... public function testPostActionShouldReceivePostParams() { // Set POST variables: $this->request->setPost(array( 'foo' => 'bar', 'bar' => 'baz', )); } // ... } 44
    • Testing COOKIE params class IndexControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { // ... public function testCookieActionShouldReceiveCookieParams() { // First set a cookie value $this->request->setCookie('username', 'DragonBe'); // Or set multiple cookies at once $this->request->setCookies(array( 'last_seen' => time(), 'userlevel' => 'Admin', )); } // ... } 45
    • Let’s dispatch it class IndexControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { // ... public function testCookieActionShouldReceiveCookieParams() { // First set a cookie value $this->request->setCookie('username', 'DragonBe'); // Or set multiple cookies at once $this->request->setCookies(array( 'last_seen' => time(), 'userlevel' => 'Admin', )); // Let’s define the request method $this->request->setMethod('POST'); // Dispatch the homepage $this->dispatch('/'); } // ... } 46
    • Demo • Using Zend Framework “QuickStart” app http://framework.zend.com/docs/quickstart - modified with ✓ detail entry • Downloads provided on http://mvandam.com/demos/zftest.zip 47
    • Interesting Readings • PHPUnit by Sebastian Bergmann http://phpunit.de • Art of Unit Testing by Roy Osherove http://artofunittesting.com • Mike Lively’s blog http://www.ds-o.com/archives/63-PHPUnit-Database-Extension-DBUnit-Port.html • Zend Framework Manual: Zend_Test http://framework.zend.com/manual/en/zend.test.phpunit.html 48
    • Questions ? Thank you. This presentation will be available on http://slideshare.com/DragonBe 49