KEMBAR78
Advanced php testing in action | PDF
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

Advanced php testing in action

  • 6.
    watch -n 15-d find tests/ -mmin -1 -iname '"*.php"' -exec 'phpunit -c tests/phpunit.xml {} ;'
  • 16.
  • 23.
    library !"" Controller.php !"" Response.php !""Request.php !"" View.php # !"" Request #   $"" Http.php !"" Response #   $"" Http.php !"" Test #   $"" ControllerTestCase.php $"" View    $"" Html.php
  • 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
  • 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';
  • 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>
  • 34.
  • 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) ); } }
  • 47.
  • 51.
  • 53.
    <?php class InterfaceTest extendsPHPUnit_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")); } }
  • 55.
    <?php class InterfaceTest extendsPHPUnit_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/"); }
  • 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 extendsRequest { public function isPost() { return ('POST' === $_SERVER['REQUEST_METHOD']); } public function isAjax() { return ('XMLHttpRequest' === $_SERVER['X_REQUESTED_WITH']); } }
  • 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 }
  • 74.
    $controller = newIndexController(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();
  • 76.
    <?php class Test_ControllerTestCase extendsPHPUnit_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); } }
  • 77.
  • 78.
    <?php class IndexControllerTest extendsTest_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); }
  • 82.
    <?php class IndexControllerTest extendsTest_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; }
  • 84.
  • 86.
    <?php class IndexControllerTest extendsTest_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' ); }
  • 88.
  • 90.
    ➡ ➡ ➡