SlideShare a Scribd company logo
1 of 92
Download to read offline
watch -n 15 -d 
   find tests/ -mmin -1 -iname '"*.php"' -exec 
   'phpunit -c tests/phpunit.xml {} ;'
➡
➡
➡
➡
library
!"" Controller.php
!"" Response.php
!"" Request.php
!"" View.php
#
!"" Request
#   $"" Http.php
!"" Response
#   $"" Http.php
!"" Test
#   $"" ControllerTestCase.php
$"" View
     $"" Html.php
project
!"" application
#   !"" controllers
#   #   $"" IndexController.php
#   !"" models
#   #   $"" Todo.php
#   $"" views
#       $"" index.phtml
$"" tests
    !"" application
    #   !"" controllers
    #   #   $"" IndexControllerTest.php
    #   !"" models
    #   #   $"" TodoTest.php
    #   $"" views
    #       $"" InterfaceTest.php
    !"" bootstrap.php
    $"" phpunit.xml
CREATE DATABASE `testing` CHARSET=utf8;
USE `testing`;

CREATE TABLE `todo` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '        ',
  `task` varchar(100) NOT NULL COMMENT '   ',
  `done` enum('y','n') NOT NULL DEFAULT 'n' COMMENT '       ',
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Todo';
<phpunit colors="true" bootstrap="./bootstrap.php">
  <testsuite name="Application Test Suite">
    <directory>./application</directory>
  </testsuite>
  <testsuite name="Library Test Suite">
    <directory>./library</directory>
  </testsuite>
  <php>
    <var name="DB_DSN" value="mysql:dbname=testing;host=127.0.0.1" />
    <var name="DB_USER" value="username" />
    <var name="DB_PASSWD" value="password" />
  </php>
</phpunit>
➡ fetchAll()
➡ add($task)
➡ done($id)
<?php                                         <?php

class TodoTest extends                        class Todo
    PHPUnit_Framework_TestCase                {
{                                                 protected static $_pdo = null;
    private $_pdo = null;                         
                                                  public static function setDb(PDO $pdo)
    private $_todo = null;                        {
                                                      self::$_pdo = $pdo;
    public function setUp()                       }
    {
        $this->_pdo = new PDO(
                $GLOBALS['DB_DSN'],
                $GLOBALS['DB_USER'],
                $GLOBALS['DB_PASSWD']);
        $this->_pdo
            ->query('TRUNCATE TABLE todo');

        Todo::setDb($this->_pdo);
        $this->_todo = new Todo();
    }

    public function tearDown()
    {
        $this->_pdo
            ->query('TRUNCATE TABLE todo');
    }
public function testAdd()                 public function add($task)
{                                         {
    $this->assertEquals(                      $query = 'INSERT INTO todo (task) '
        1,                                           . 'VALUES (?)';
        $this->_todo->add('Task 1')
    );                                        self::$_pdo->prepare($query)
                                                  ->execute(array($task));
    $this->assertEquals(
        2,                                    return self::$_pdo->lastInsertId();
        $this->_todo->add('Task 2')       }
    );                                    
}
public function testFetchAll()                  public function fetchAll()
{                                               {
    $this->_todo->add('Task 1', 'm');               $query = 'SELECT * FROM todo';
    $this->_todo->add('Task 2', 'f');               $stmt  = self::$_pdo
                                                        ->query($query);
    $result = $this->_todo->fetchAll();
                                                  return $stmt
    $this->assertEquals(                              ->fetchAll(PDO::FETCH_ASSOC);
        2,                                    }
        count($result)
    );

    $this->assertContains(
       'Task 1',
        $result[0]
    );

    $this->assertContains(
       'Task 2',
        $result[1]
    );
}
public function testDone()             public function done($id)
    {                                      {
        $this->_todo->add('Task 1');           $query = 'UPDATE todo '
        $this->_todo->add('Task 2');                  . 'SET done = 'y''
                                                      . 'WHERE id = ?';
        $this->assertEquals(                   $stmt  = self::$_pdo->prepare($query);
            1,
            $this->_todo->done(1)              $stmt->execute(array($id));
        );
                                               return $stmt->rowCount();
        $this->assertEquals(               }
            1,                         }
            $this->_todo->done(2)
        );

        $this->assertEquals(
            0,
            $this->_todo->done(3)
        );
    }
}
➡	 
➡
➡
➡
➡
➡
<?php

class InterfaceTest extends PHPUnit_Extensions_SeleniumTestCase
{

    protected function setUp()
    {
        $this->setBrowser("*chrome");
        $this->setBrowserUrl("http://test.dev/");
    }

    public function testMyTestCase()
    {
        $this->open("/advanced_php_testing/mvc/");
        $this->type("id=new-todo", "Task 1");
        $this->keyPress("id=new-todo", "13");
        $this->waitForPageToLoad("30000");
        $this->assertEquals("Task 1",
            $this->getText("//ul[@id='todo-list']/div[1]/div/div"));
        $this->type("id=new-todo", "Task 2");
        $this->keyPress("id=new-todo", "13");
        $this->waitForPageToLoad("30000");
        $this->assertEquals("Task 2",
            $this->getText("//ul[@id='todo-list']/div[2]/div/div"));
    }
}
<?php

class InterfaceTest extends PHPUnit_Extensions_SeleniumTestCase
{

    protected function setUp()
    {
        $this->_pdo = new PDO(
                        $GLOBALS['DB_DSN'],
                        $GLOBALS['DB_USER'],
                        $GLOBALS['DB_PASSWD']);
        $this->_pdo->query('TRUNCATE TABLE todo');

        Todo::setDb($this->_pdo);
        $this->_todo = new Todo();

        $this->setBrowser("*chrome");
        $this->setBrowserUrl("http://test.dev/");
    }
<?php

class Request
{
    protected $_headers = array(
        'REQUEST_METHOD' => 'GET',
    );

    public function setHeader($name, $value)
    {
        $this->_headers[$name] = $value;
    }

    public function isPost()
    {
        return ('POST' === $this->_headers['REQUEST_METHOD']);
    }

    public function isAjax()
    {
        return ('XMLHttpRequest' === $this->_headers['X_REQUESTED_WITH']);
    }
<?php

class Request_Http extends Request
{
    public function isPost()
    {
        return ('POST' === $_SERVER['REQUEST_METHOD']);
    }

    public function isAjax()
    {
        return ('XMLHttpRequest' === $_SERVER['X_REQUESTED_WITH']);
    }
}
<?php

class Response
{
    protected $_headers = array(
        'Content-Type' => 'text/html; charset=utf-8',
    );

    public function setHeader($name, $content)
    {
        $this->_headers[$name] = $content;
    }

    public function getHeader($name)
    {
        return isset($this->_headers[$name])
             ? $this->_headers[$name]
             : null;
    }

    protected function sendHeaders()
    {
        // do nothing
    }
$controller = new IndexController(new Todo());
$controller->setRequest(new Request_Http())
        ->setResponse(new Response_Http())
        ->sendResponse(true)
        ->dispatch();




$controller = new IndexController(new Todo());
$controller->setRequest(new Request())
        ->setResponse(new Response())
        ->dispatch();
<?php

class Test_ControllerTestCase extends PHPUnit_Framework_TestCase
{
    protected $_controller = null;

    protected $_request = null;

    protected $_response = null;

    public function setUp()
    {
        $this->_controller->setRequest($this->_request)
                            ->setResponse($this->_response);
    }

    public function dispatch($url)
    {
        $this->_parseUrl($url);
        $this->_controller->dispatch();
        return $this;
    }

    protected function _parseUrl($url)
    {
        $urlInfo = parse_url($url);
        if (isset($urlInfo['query'])) {
            parse_str($urlInfo['query'], $_GET);
        }
    }
➡ assertAction($action)
➡ assertResponseCode($code)
➡ assertRedirectTo($url)
<?php

class IndexControllerTest extends Test_ControllerTestCase
{
    public function setUp()
    {
        $todo = new Todo();
        $this->_request = new Request();
        $this->_response = new Response();
        $this->_controller = new IndexController($todo);
        parent::setUp();
    }

    public function tearDown()
    {
        $this->_request->reset();
        $this->_response->reset();
    }

    public function testHome()
    {
        $this->dispatch('/');
        $this->assertAction('index')
                ->assertResponseCode(200);
    }
<?php

class IndexControllerTest extends Test_ControllerTestCase
{
    public function setUp()
    {
        $todo = $this->_setUpTodo();
        $this->_controller = new IndexController($todo);
        // ...
    }

    protected function _setUpTodo()
    {
        $todo = Phake::mock('Todo');
        Phake::when($todo)->fetchAll()->thenReturn(array(
            array(
                'id' => 1,
                'task' => 'Task 1',
                'done' => 'n',
            ),
        ));
        return $todo;
    }
➡ assertQuery($selector)
➡ assertQueryContain($selector, $text)
<?php

class IndexControllerTest extends Test_ControllerTestCase
{
    // ...

    public function testHome()
    {
        $this->dispatch('/');
        $this->assertAction('index')
                ->assertResponseCode(200)
                ->assertQuery('#todo-list');
    }

    public function testAdd()
    {
        $this->_request->setMethod('POST');
        $_POST['task'] = 'Task 1';
        $this->dispatch('/?act=add')
                ->assertAction('add')
                ->assertRedirectTo('./')
                ->assertResponseCode(200)
                ->assertQueryContain(
                    '#todo-list>.todo>.display>.todo-text',
                    'Task 1'
                );
    }
➡

➡

➡
➡	               	 


➡	              	 


➡	    	               	 
                           	 
➡
Advanced php testing in action
Advanced php testing in action

More Related Content

What's hot

Php tips-and-tricks4128
Php tips-and-tricks4128Php tips-and-tricks4128
Php tips-and-tricks4128
PrinceGuru MS
 
Design Patterns in PHP5
Design Patterns in PHP5 Design Patterns in PHP5
Design Patterns in PHP5
Wildan Maulana
 
Система рендеринга в Magento
Система рендеринга в MagentoСистема рендеринга в Magento
Система рендеринга в Magento
Magecom Ukraine
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
Fabien Potencier
 
Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3
Fabien Potencier
 

What's hot (20)

Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownparts
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
 
PHP Data Objects
PHP Data ObjectsPHP Data Objects
PHP Data Objects
 
Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnit
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
Php tips-and-tricks4128
Php tips-and-tricks4128Php tips-and-tricks4128
Php tips-and-tricks4128
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & REST
 
Things I Believe Now That I'm Old
Things I Believe Now That I'm OldThings I Believe Now That I'm Old
Things I Believe Now That I'm Old
 
Design Patterns in PHP5
Design Patterns in PHP5 Design Patterns in PHP5
Design Patterns in PHP5
 
Doctrine 2
Doctrine 2Doctrine 2
Doctrine 2
 
PHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにPHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くために
 
Система рендеринга в Magento
Система рендеринга в MagentoСистема рендеринга в Magento
Система рендеринга в Magento
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needDutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP Generators
 
Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3
 

Viewers also liked

Advanced PHP: Design Patterns - Dennis-Jan Broerse
Advanced PHP: Design Patterns - Dennis-Jan BroerseAdvanced PHP: Design Patterns - Dennis-Jan Broerse
Advanced PHP: Design Patterns - Dennis-Jan Broerse
dpc
 

Viewers also liked (17)

PHPUnit 入門介紹
PHPUnit 入門介紹PHPUnit 入門介紹
PHPUnit 入門介紹
 
Refactoring with Patterns in PHP
Refactoring with Patterns in PHPRefactoring with Patterns in PHP
Refactoring with Patterns in PHP
 
第一次用 PHPUnit 寫測試就上手
第一次用 PHPUnit 寫測試就上手第一次用 PHPUnit 寫測試就上手
第一次用 PHPUnit 寫測試就上手
 
PHP 防駭 - 基礎觀念篇
PHP 防駭 - 基礎觀念篇PHP 防駭 - 基礎觀念篇
PHP 防駭 - 基礎觀念篇
 
Php Security By Mugdha And Anish
Php Security By Mugdha And AnishPhp Security By Mugdha And Anish
Php Security By Mugdha And Anish
 
PHP Advanced
PHP AdvancedPHP Advanced
PHP Advanced
 
Advanced Php - Macq Electronique 2010
Advanced Php - Macq Electronique 2010Advanced Php - Macq Electronique 2010
Advanced Php - Macq Electronique 2010
 
Advanced PHP Simplified
Advanced PHP SimplifiedAdvanced PHP Simplified
Advanced PHP Simplified
 
Advanced PHP Web Development Tools in 2015
Advanced PHP Web Development Tools in 2015Advanced PHP Web Development Tools in 2015
Advanced PHP Web Development Tools in 2015
 
PHP 物件導向 - 基礎觀念篇
PHP 物件導向 - 基礎觀念篇PHP 物件導向 - 基礎觀念篇
PHP 物件導向 - 基礎觀念篇
 
What happens in laravel 4 bootstraping
What happens in laravel 4 bootstrapingWhat happens in laravel 4 bootstraping
What happens in laravel 4 bootstraping
 
DIWE - Advanced PHP Concepts
DIWE - Advanced PHP ConceptsDIWE - Advanced PHP Concepts
DIWE - Advanced PHP Concepts
 
Advanced PHP: Design Patterns - Dennis-Jan Broerse
Advanced PHP: Design Patterns - Dennis-Jan BroerseAdvanced PHP: Design Patterns - Dennis-Jan Broerse
Advanced PHP: Design Patterns - Dennis-Jan Broerse
 
PHP Web Programming
PHP Web ProgrammingPHP Web Programming
PHP Web Programming
 
Introduction to PHP
Introduction to PHPIntroduction to PHP
Introduction to PHP
 
PHP Powerpoint -- Teach PHP with this
PHP Powerpoint -- Teach PHP with thisPHP Powerpoint -- Teach PHP with this
PHP Powerpoint -- Teach PHP with this
 
Php Presentation
Php PresentationPhp Presentation
Php Presentation
 

Similar to Advanced php testing in action

Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnit
mfrost503
 
Object Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOPObject Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOP
Wildan Maulana
 
R57shell
R57shellR57shell
R57shell
ady36
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
jsmith92
 

Similar to Advanced php testing in action (20)

Workshop unittesting
Workshop unittestingWorkshop unittesting
Workshop unittesting
 
Presentation1
Presentation1Presentation1
Presentation1
 
Oops in php
Oops in phpOops in php
Oops in php
 
Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnit
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Object Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOPObject Oriented Programming with PHP 5 - More OOP
Object Oriented Programming with PHP 5 - More OOP
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
 
R57shell
R57shellR57shell
R57shell
 
Bacbkone js
Bacbkone jsBacbkone js
Bacbkone js
 
PHPSpec BDD for PHP
PHPSpec BDD for PHPPHPSpec BDD for PHP
PHPSpec BDD for PHP
 
linieaire regressie
linieaire regressielinieaire regressie
linieaire regressie
 
Pim Elshoff "Technically DDD"
Pim Elshoff "Technically DDD"Pim Elshoff "Technically DDD"
Pim Elshoff "Technically DDD"
 
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
 

More from Jace Ju (9)

深入淺出 MVC
深入淺出 MVC深入淺出 MVC
深入淺出 MVC
 
如何打造 WebMVC Framework - 基礎概念篇
如何打造 WebMVC Framework - 基礎概念篇如何打造 WebMVC Framework - 基礎概念篇
如何打造 WebMVC Framework - 基礎概念篇
 
Patterns in Library Design (套件設計裡的模式)
Patterns in Library Design (套件設計裡的模式)Patterns in Library Design (套件設計裡的模式)
Patterns in Library Design (套件設計裡的模式)
 
Patterns in Zend Framework
Patterns in Zend FrameworkPatterns in Zend Framework
Patterns in Zend Framework
 
Head First Zend Framework - Part 1 Project & Application
Head First Zend Framework - Part 1 Project & ApplicationHead First Zend Framework - Part 1 Project & Application
Head First Zend Framework - Part 1 Project & Application
 
常見設計模式介紹
常見設計模式介紹常見設計模式介紹
常見設計模式介紹
 
Web Refactoring
Web RefactoringWeb Refactoring
Web Refactoring
 
jQuery 實戰經驗講座
jQuery 實戰經驗講座jQuery 實戰經驗講座
jQuery 實戰經驗講座
 
CSS 排版 - 基礎觀念篇
CSS 排版 - 基礎觀念篇CSS 排版 - 基礎觀念篇
CSS 排版 - 基礎觀念篇
 

Recently uploaded

Recently uploaded (20)

Strategic AI Integration in Engineering Teams
Strategic AI Integration in Engineering TeamsStrategic AI Integration in Engineering Teams
Strategic AI Integration in Engineering Teams
 
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
SOQL 201 for Admins & Developers: Slice & Dice Your Org’s Data With Aggregate...
 
PLAI - Acceleration Program for Generative A.I. Startups
PLAI - Acceleration Program for Generative A.I. StartupsPLAI - Acceleration Program for Generative A.I. Startups
PLAI - Acceleration Program for Generative A.I. Startups
 
ASRock Industrial FDO Solutions in Action for Industrial Edge AI _ Kenny at A...
ASRock Industrial FDO Solutions in Action for Industrial Edge AI _ Kenny at A...ASRock Industrial FDO Solutions in Action for Industrial Edge AI _ Kenny at A...
ASRock Industrial FDO Solutions in Action for Industrial Edge AI _ Kenny at A...
 
Free and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi IbrahimzadeFree and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
 
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
Measures in SQL (a talk at SF Distributed Systems meetup, 2024-05-22)
 
The Metaverse: Are We There Yet?
The  Metaverse:    Are   We  There  Yet?The  Metaverse:    Are   We  There  Yet?
The Metaverse: Are We There Yet?
 
THE BEST IPTV in GERMANY for 2024: IPTVreel
THE BEST IPTV in  GERMANY for 2024: IPTVreelTHE BEST IPTV in  GERMANY for 2024: IPTVreel
THE BEST IPTV in GERMANY for 2024: IPTVreel
 
A Business-Centric Approach to Design System Strategy
A Business-Centric Approach to Design System StrategyA Business-Centric Approach to Design System Strategy
A Business-Centric Approach to Design System Strategy
 
Integrating Telephony Systems with Salesforce: Insights and Considerations, B...
Integrating Telephony Systems with Salesforce: Insights and Considerations, B...Integrating Telephony Systems with Salesforce: Insights and Considerations, B...
Integrating Telephony Systems with Salesforce: Insights and Considerations, B...
 
Where to Learn More About FDO _ Richard at FIDO Alliance.pdf
Where to Learn More About FDO _ Richard at FIDO Alliance.pdfWhere to Learn More About FDO _ Richard at FIDO Alliance.pdf
Where to Learn More About FDO _ Richard at FIDO Alliance.pdf
 
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptx
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptxUnpacking Value Delivery - Agile Oxford Meetup - May 2024.pptx
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptx
 
WSO2CONMay2024OpenSourceConferenceDebrief.pptx
WSO2CONMay2024OpenSourceConferenceDebrief.pptxWSO2CONMay2024OpenSourceConferenceDebrief.pptx
WSO2CONMay2024OpenSourceConferenceDebrief.pptx
 
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya HalderCustom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
 
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdfThe Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
 
Oauth 2.0 Introduction and Flows with MuleSoft
Oauth 2.0 Introduction and Flows with MuleSoftOauth 2.0 Introduction and Flows with MuleSoft
Oauth 2.0 Introduction and Flows with MuleSoft
 
Intro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджераIntro in Product Management - Коротко про професію продакт менеджера
Intro in Product Management - Коротко про професію продакт менеджера
 
Google I/O Extended 2024 Warsaw
Google I/O Extended 2024 WarsawGoogle I/O Extended 2024 Warsaw
Google I/O Extended 2024 Warsaw
 
Linux Foundation Edge _ Overview of FDO Software Components _ Randy at Intel.pdf
Linux Foundation Edge _ Overview of FDO Software Components _ Randy at Intel.pdfLinux Foundation Edge _ Overview of FDO Software Components _ Randy at Intel.pdf
Linux Foundation Edge _ Overview of FDO Software Components _ Randy at Intel.pdf
 
IESVE for Early Stage Design and Planning
IESVE for Early Stage Design and PlanningIESVE for Early Stage Design and Planning
IESVE for Early Stage Design and Planning
 

Advanced php testing in action

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6. watch -n 15 -d find tests/ -mmin -1 -iname '"*.php"' -exec 'phpunit -c tests/phpunit.xml {} ;'
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23. library !"" Controller.php !"" Response.php !"" Request.php !"" View.php # !"" Request #   $"" Http.php !"" Response #   $"" Http.php !"" Test #   $"" ControllerTestCase.php $"" View    $"" Html.php
  • 24.
  • 25.
  • 26. project !"" application #   !"" controllers #   #   $"" IndexController.php #   !"" models #   #   $"" Todo.php #   $"" views #   $"" index.phtml $"" tests !"" application #   !"" controllers #   #   $"" IndexControllerTest.php #   !"" models #   #   $"" TodoTest.php #   $"" views #   $"" InterfaceTest.php !"" bootstrap.php $"" phpunit.xml
  • 27.
  • 28.
  • 29.
  • 30.
  • 31. CREATE DATABASE `testing` CHARSET=utf8; USE `testing`; CREATE TABLE `todo` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT ' ', `task` varchar(100) NOT NULL COMMENT ' ', `done` enum('y','n') NOT NULL DEFAULT 'n' COMMENT ' ', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Todo';
  • 32.
  • 33. <phpunit colors="true" bootstrap="./bootstrap.php"> <testsuite name="Application Test Suite"> <directory>./application</directory> </testsuite> <testsuite name="Library Test Suite"> <directory>./library</directory> </testsuite> <php> <var name="DB_DSN" value="mysql:dbname=testing;host=127.0.0.1" /> <var name="DB_USER" value="username" /> <var name="DB_PASSWD" value="password" /> </php> </phpunit>
  • 35.
  • 36. <?php <?php class TodoTest extends class Todo PHPUnit_Framework_TestCase { {     protected static $_pdo = null; private $_pdo = null;          public static function setDb(PDO $pdo) private $_todo = null;     {         self::$_pdo = $pdo; public function setUp()     } { $this->_pdo = new PDO( $GLOBALS['DB_DSN'], $GLOBALS['DB_USER'], $GLOBALS['DB_PASSWD']); $this->_pdo ->query('TRUNCATE TABLE todo'); Todo::setDb($this->_pdo); $this->_todo = new Todo(); } public function tearDown() { $this->_pdo ->query('TRUNCATE TABLE todo'); }
  • 37. public function testAdd()     public function add($task) {     { $this->assertEquals(         $query = 'INSERT INTO todo (task) ' 1,  . 'VALUES (?)'; $this->_todo->add('Task 1') );         self::$_pdo->prepare($query) ->execute(array($task)); $this->assertEquals( 2,         return self::$_pdo->lastInsertId(); $this->_todo->add('Task 2')     } );      }
  • 38. public function testFetchAll()     public function fetchAll() {     { $this->_todo->add('Task 1', 'm');         $query = 'SELECT * FROM todo'; $this->_todo->add('Task 2', 'f');         $stmt  = self::$_pdo ->query($query); $result = $this->_todo->fetchAll();         return $stmt $this->assertEquals( ->fetchAll(PDO::FETCH_ASSOC); 2,     } count($result) ); $this->assertContains( 'Task 1', $result[0] ); $this->assertContains( 'Task 2', $result[1] ); }
  • 39. public function testDone()     public function done($id) {     { $this->_todo->add('Task 1');         $query = 'UPDATE todo ' $this->_todo->add('Task 2');  . 'SET done = 'y''  . 'WHERE id = ?'; $this->assertEquals(         $stmt  = self::$_pdo->prepare($query); 1, $this->_todo->done(1)         $stmt->execute(array($id)); );         return $stmt->rowCount(); $this->assertEquals(     } 1, } $this->_todo->done(2) ); $this->assertEquals( 0, $this->_todo->done(3) ); } }
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 48.
  • 49.
  • 50.
  • 52.
  • 53. <?php class InterfaceTest extends PHPUnit_Extensions_SeleniumTestCase { protected function setUp() { $this->setBrowser("*chrome"); $this->setBrowserUrl("http://test.dev/"); } public function testMyTestCase() { $this->open("/advanced_php_testing/mvc/"); $this->type("id=new-todo", "Task 1"); $this->keyPress("id=new-todo", "13"); $this->waitForPageToLoad("30000"); $this->assertEquals("Task 1", $this->getText("//ul[@id='todo-list']/div[1]/div/div")); $this->type("id=new-todo", "Task 2"); $this->keyPress("id=new-todo", "13"); $this->waitForPageToLoad("30000"); $this->assertEquals("Task 2", $this->getText("//ul[@id='todo-list']/div[2]/div/div")); } }
  • 54.
  • 55. <?php class InterfaceTest extends PHPUnit_Extensions_SeleniumTestCase { protected function setUp() { $this->_pdo = new PDO( $GLOBALS['DB_DSN'], $GLOBALS['DB_USER'], $GLOBALS['DB_PASSWD']); $this->_pdo->query('TRUNCATE TABLE todo'); Todo::setDb($this->_pdo); $this->_todo = new Todo(); $this->setBrowser("*chrome"); $this->setBrowserUrl("http://test.dev/"); }
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69. <?php class Request { protected $_headers = array( 'REQUEST_METHOD' => 'GET', ); public function setHeader($name, $value) { $this->_headers[$name] = $value; } public function isPost() { return ('POST' === $this->_headers['REQUEST_METHOD']); } public function isAjax() { return ('XMLHttpRequest' === $this->_headers['X_REQUESTED_WITH']); }
  • 70. <?php class Request_Http extends Request { public function isPost() { return ('POST' === $_SERVER['REQUEST_METHOD']); } public function isAjax() { return ('XMLHttpRequest' === $_SERVER['X_REQUESTED_WITH']); } }
  • 71.
  • 72. <?php class Response { protected $_headers = array( 'Content-Type' => 'text/html; charset=utf-8', ); public function setHeader($name, $content) { $this->_headers[$name] = $content; } public function getHeader($name) { return isset($this->_headers[$name]) ? $this->_headers[$name] : null; } protected function sendHeaders() { // do nothing }
  • 73.
  • 74. $controller = new IndexController(new Todo()); $controller->setRequest(new Request_Http()) ->setResponse(new Response_Http()) ->sendResponse(true) ->dispatch(); $controller = new IndexController(new Todo()); $controller->setRequest(new Request()) ->setResponse(new Response()) ->dispatch();
  • 75.
  • 76. <?php class Test_ControllerTestCase extends PHPUnit_Framework_TestCase { protected $_controller = null; protected $_request = null; protected $_response = null; public function setUp() { $this->_controller->setRequest($this->_request) ->setResponse($this->_response); } public function dispatch($url) { $this->_parseUrl($url); $this->_controller->dispatch(); return $this; } protected function _parseUrl($url) { $urlInfo = parse_url($url); if (isset($urlInfo['query'])) { parse_str($urlInfo['query'], $_GET); } }
  • 78. <?php class IndexControllerTest extends Test_ControllerTestCase { public function setUp() { $todo = new Todo(); $this->_request = new Request(); $this->_response = new Response(); $this->_controller = new IndexController($todo); parent::setUp(); } public function tearDown() { $this->_request->reset(); $this->_response->reset(); } public function testHome() { $this->dispatch('/'); $this->assertAction('index') ->assertResponseCode(200); }
  • 79.
  • 80.
  • 81.
  • 82. <?php class IndexControllerTest extends Test_ControllerTestCase { public function setUp() { $todo = $this->_setUpTodo(); $this->_controller = new IndexController($todo); // ... } protected function _setUpTodo() { $todo = Phake::mock('Todo'); Phake::when($todo)->fetchAll()->thenReturn(array( array( 'id' => 1, 'task' => 'Task 1', 'done' => 'n', ), )); return $todo; }
  • 83.
  • 85.
  • 86. <?php class IndexControllerTest extends Test_ControllerTestCase { // ... public function testHome() { $this->dispatch('/'); $this->assertAction('index') ->assertResponseCode(200) ->assertQuery('#todo-list'); } public function testAdd() { $this->_request->setMethod('POST'); $_POST['task'] = 'Task 1'; $this->dispatch('/?act=add') ->assertAction('add') ->assertRedirectTo('./') ->assertResponseCode(200) ->assertQueryContain( '#todo-list>.todo>.display>.todo-text', 'Task 1' ); }
  • 87.
  • 89.
  • 90. ➡ ➡ ➡