SlideShare a Scribd company logo
1 of 49
Download to read offline
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

More Related Content

What's hot

Unit Testing And Mocking
Unit Testing And MockingUnit Testing And Mocking
Unit Testing And Mocking
Joe Wilson
 

What's hot (20)

Java. Explicit and Implicit Wait. Testing Ajax Applications
Java. Explicit and Implicit Wait. Testing Ajax ApplicationsJava. Explicit and Implicit Wait. Testing Ajax Applications
Java. Explicit and Implicit Wait. Testing Ajax Applications
 
Unit Testng with PHP Unit - A Step by Step Training
Unit Testng with PHP Unit - A Step by Step TrainingUnit Testng with PHP Unit - A Step by Step Training
Unit Testng with PHP Unit - A Step by Step Training
 
TestNG
TestNGTestNG
TestNG
 
REST-API introduction for developers
REST-API introduction for developersREST-API introduction for developers
REST-API introduction for developers
 
Introduction to Node.js
Introduction to Node.jsIntroduction to Node.js
Introduction to Node.js
 
Spring Boot and REST API
Spring Boot and REST APISpring Boot and REST API
Spring Boot and REST API
 
JUnit Presentation
JUnit PresentationJUnit Presentation
JUnit Presentation
 
Understanding REST
Understanding RESTUnderstanding REST
Understanding REST
 
Unit Testing And Mocking
Unit Testing And MockingUnit Testing And Mocking
Unit Testing And Mocking
 
Node js overview
Node js overviewNode js overview
Node js overview
 
Test your microservices with REST-Assured
Test your microservices with REST-AssuredTest your microservices with REST-Assured
Test your microservices with REST-Assured
 
JUnit 5
JUnit 5JUnit 5
JUnit 5
 
Node.js Express Framework
Node.js Express FrameworkNode.js Express Framework
Node.js Express Framework
 
An Overview of Web Services: SOAP and REST
An Overview of Web Services: SOAP and REST An Overview of Web Services: SOAP and REST
An Overview of Web Services: SOAP and REST
 
Express node js
Express node jsExpress node js
Express node js
 
Node.Js: Basics Concepts and Introduction
Node.Js: Basics Concepts and Introduction Node.Js: Basics Concepts and Introduction
Node.Js: Basics Concepts and Introduction
 
Asynchronous JavaScript Programming
Asynchronous JavaScript ProgrammingAsynchronous JavaScript Programming
Asynchronous JavaScript Programming
 
An Introduction To REST API
An Introduction To REST APIAn Introduction To REST API
An Introduction To REST API
 
Http methods
Http methodsHttp methods
Http methods
 
Junit
JunitJunit
Junit
 

Similar to Introduction to Unit Testing with PHPUnit

New Features PHPUnit 3.3 - Sebastian Bergmann
New Features PHPUnit 3.3 - Sebastian BergmannNew Features PHPUnit 3.3 - Sebastian Bergmann
New Features PHPUnit 3.3 - Sebastian Bergmann
dpc
 
Unit Testing using PHPUnit
Unit Testing using  PHPUnitUnit Testing using  PHPUnit
Unit Testing using PHPUnit
varuntaliyan
 
Beginning PHPUnit
Beginning PHPUnitBeginning PHPUnit
Beginning PHPUnit
Jace Ju
 
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur PurnamaEPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
Enterprise PHP Center
 

Similar to Introduction to Unit Testing with PHPUnit (20)

PHPUnit testing to Zend_Test
PHPUnit testing to Zend_TestPHPUnit testing to Zend_Test
PHPUnit testing to Zend_Test
 
Php Unit With Zend Framework Zendcon09
Php Unit With Zend Framework   Zendcon09Php Unit With Zend Framework   Zendcon09
Php Unit With Zend Framework Zendcon09
 
New Features PHPUnit 3.3 - Sebastian Bergmann
New Features PHPUnit 3.3 - Sebastian BergmannNew Features PHPUnit 3.3 - Sebastian Bergmann
New Features PHPUnit 3.3 - Sebastian Bergmann
 
Unlock The Mystery Of PHPUnit (Wave PHP 2018)
Unlock The Mystery Of PHPUnit (Wave PHP 2018)Unlock The Mystery Of PHPUnit (Wave PHP 2018)
Unlock The Mystery Of PHPUnit (Wave PHP 2018)
 
Php unit (eng)
Php unit (eng)Php unit (eng)
Php unit (eng)
 
13 PHPUnit #burningkeyboards
13 PHPUnit #burningkeyboards13 PHPUnit #burningkeyboards
13 PHPUnit #burningkeyboards
 
Unit Testing using PHPUnit
Unit Testing using  PHPUnitUnit Testing using  PHPUnit
Unit Testing using PHPUnit
 
Beginning PHPUnit
Beginning PHPUnitBeginning PHPUnit
Beginning PHPUnit
 
Advanced PHPUnit Testing
Advanced PHPUnit TestingAdvanced PHPUnit Testing
Advanced PHPUnit Testing
 
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur PurnamaEPHPC Webinar Slides: Unit Testing by Arthur Purnama
EPHPC Webinar Slides: Unit Testing by Arthur Purnama
 
Phpunit
PhpunitPhpunit
Phpunit
 
PHPUnit best practices presentation
PHPUnit best practices presentationPHPUnit best practices presentation
PHPUnit best practices presentation
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12
 
PHPSpec BDD Framework
PHPSpec BDD FrameworkPHPSpec BDD Framework
PHPSpec BDD Framework
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
 
Commencer avec le TDD
Commencer avec le TDDCommencer avec le TDD
Commencer avec le TDD
 
Unit testing
Unit testingUnit testing
Unit testing
 
Getting started with TDD - Confoo 2014
Getting started with TDD - Confoo 2014Getting started with TDD - Confoo 2014
Getting started with TDD - Confoo 2014
 
PHPunit and you
PHPunit and youPHPunit and you
PHPunit and you
 
Leveling Up With Unit Testing - php[tek] 2023
Leveling Up With Unit Testing - php[tek] 2023Leveling Up With Unit Testing - php[tek] 2023
Leveling Up With Unit Testing - php[tek] 2023
 

More from Michelangelo van Dam

Zf2 how arrays will save your project
Zf2   how arrays will save your projectZf2   how arrays will save your project
Zf2 how arrays will save your project
Michelangelo van Dam
 

More from Michelangelo van Dam (20)

GDPR Art. 25 - Privacy by design and default
GDPR Art. 25 - Privacy by design and defaultGDPR Art. 25 - Privacy by design and default
GDPR Art. 25 - Privacy by design and default
 
Moving from app services to azure functions
Moving from app services to azure functionsMoving from app services to azure functions
Moving from app services to azure functions
 
Privacy by design
Privacy by designPrivacy by design
Privacy by design
 
DevOps or DevSecOps
DevOps or DevSecOpsDevOps or DevSecOps
DevOps or DevSecOps
 
Privacy by design
Privacy by designPrivacy by design
Privacy by design
 
Continuous deployment 2.0
Continuous deployment 2.0Continuous deployment 2.0
Continuous deployment 2.0
 
Let your tests drive your code
Let your tests drive your codeLet your tests drive your code
Let your tests drive your code
 
General Data Protection Regulation, a developer's story
General Data Protection Regulation, a developer's storyGeneral Data Protection Regulation, a developer's story
General Data Protection Regulation, a developer's story
 
Leveraging a distributed architecture to your advantage
Leveraging a distributed architecture to your advantageLeveraging a distributed architecture to your advantage
Leveraging a distributed architecture to your advantage
 
The road to php 7.1
The road to php 7.1The road to php 7.1
The road to php 7.1
 
Open source for a successful business
Open source for a successful businessOpen source for a successful business
Open source for a successful business
 
Decouple your framework now, thank me later
Decouple your framework now, thank me laterDecouple your framework now, thank me later
Decouple your framework now, thank me later
 
Deploy to azure in less then 15 minutes
Deploy to azure in less then 15 minutesDeploy to azure in less then 15 minutes
Deploy to azure in less then 15 minutes
 
Azure and OSS, a match made in heaven
Azure and OSS, a match made in heavenAzure and OSS, a match made in heaven
Azure and OSS, a match made in heaven
 
Getting hands dirty with php7
Getting hands dirty with php7Getting hands dirty with php7
Getting hands dirty with php7
 
Zf2 how arrays will save your project
Zf2   how arrays will save your projectZf2   how arrays will save your project
Zf2 how arrays will save your project
 
Create, test, secure, repeat
Create, test, secure, repeatCreate, test, secure, repeat
Create, test, secure, repeat
 
The Continuous PHP Pipeline
The Continuous PHP PipelineThe Continuous PHP Pipeline
The Continuous PHP Pipeline
 
PHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the testsPHPUnit Episode iv.iii: Return of the tests
PHPUnit Episode iv.iii: Return of the tests
 
Easily extend your existing php app with an api
Easily extend your existing php app with an apiEasily extend your existing php app with an api
Easily extend your existing php app with an api
 

Recently uploaded

EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Recently uploaded (20)

How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Evaluating the top large language models.pdf
Evaluating the top large language models.pdfEvaluating the top large language models.pdf
Evaluating the top large language models.pdf
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 

Introduction to Unit Testing with PHPUnit

  • 1. Introduction to Unit Testing with PHPUnit by Michelangelo van Dam
  • 2. 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
  • 3. 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
  • 4. What is Unit Testing ? Wikipedia: “is a method of testing that verifies the individual units of source code are working properly” 4
  • 5. 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
  • 6. 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
  • 7. SimpleTest • comparable to JUnit/PHPUnit • created by Marcus Baker • popular for testing web pages at browser level 7
  • 8. PHPUnit • Part of xUnit familiy (JUnit, SUnit,...) • created by Sebastian Bergmann • integrated/supported - Zend Studio - Zend Framework 8
  • 9. 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
  • 10. Hello World <?php class HelloWorld { public $helloWorld; public function __construct($string = ‘Hello World!’) { $this->helloWorld = $string; } public function sayHello() { return $this->helloWorld; } } 10
  • 11. <?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
  • 12. Testing HelloWorld # phpunit HelloWorldTest HelloWorldTest.php PHPUnit 3.3.2 by Sebastian Bergmann. .. Time: 0 seconds OK (2 tests, 2 assertions) 12
  • 13. More testing • data providers (@dataProvider) • exception (@expectedException) • fixtures (setUp() and tearDown()) • doubles (mocks and stubs) • database testing 13
  • 14. Data Provider • provides arbitrary arguments - array - object (that implements Iterator) • annotated by @dataProvider provider • multiple arguments 14
  • 15. 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
  • 16. 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
  • 17. Expected Exception • testing exceptions - that they are thrown - are properly catched 17
  • 18. 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
  • 19. Testing OopsTest # phpunit OopsTest OopsTest.php PHPUnit 3.3.2 by Sebastian Bergmann. . Time: 0 seconds OK (1 test, 0 assertions) 19
  • 20. 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
  • 21. 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
  • 22. Testing FixmeTest # phpunit FixmeTest FixmeTest.php PHPUnit 3.3.2 by Sebastian Bergmann. .. Time: 0 seconds OK (2 tests, 2 assertions) 22
  • 23. Doubles • stub objects • mock objects 23
  • 24. Stubs • isolates tests from external influences - slow connections - expensive and complex resources • replaces a “system under test” (SUT) - for the purpose of testing 24
  • 25. 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
  • 26. Testing StubTest # phpunit StubTest StubTest.php PHPUnit 3.3.2 by Sebastian Bergmann. . Time: 0 seconds OK (1 test, 1 assertion) 26
  • 27. Mocks • simulated objects • mimics API or behaviour • in a controlled way • to test a real object 27
  • 28. 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
  • 29. 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
  • 30. 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
  • 31. 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
  • 32. 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
  • 33. <?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
  • 34. 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
  • 35. Testing BankAccount # phpunit BankAccountDbTest BankAccountDbTest.php PHPUnit 3.3.2 by Sebastian Bergmann. F Time: 0 seconds There was 1 failure: ... 35
  • 36. Testing BA (2) ... 1) testNewAccountCreation(BankAccountDBTest) Failed asserting that actual +----------------------+----------------------+ | bank_account | +----------------------+----------------------+ | account_number | balance | +----------------------+----------------------+ | 12345678912345678 | 0 | +----------------------+----------------------+ | 12348612357236185 | 89 | +----------------------+----------------------+ | 15934903649620486 | 100 | +----------------------+----------------------+ | 15936487230215067 | 1216 | +----------------------+----------------------+ 36
  • 37. ... 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
  • 38. 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
  • 39. 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
  • 40. 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
  • 41. 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
  • 42. Testing homepage class IndexControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { // ... public function testHomePage() { $this->dispatch('/'); // ... } } 42
  • 43. 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
  • 44. 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
  • 45. 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
  • 46. 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
  • 47. 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
  • 48. 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
  • 49. Questions ? Thank you. This presentation will be available on http://slideshare.com/DragonBe 49