Unit & Functional Tests
Fabien Potencier
Standardization
PHPUnit 3.5
Best practices
AllTests.php
phpunit.xml(.dist)

<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         colors="false"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="true"
         stopOnFailure="false"
         syntaxCheck="false"
         bootstrap="../src/autoload.php"
>
<testsuites>
  <testsuite name="Project Test Suite">
    <directory>
      ../src/Application/*/Tests
    </directory>
  </testsuite>
</testsuites>
<filter>
  <whitelist>
    <directory>../src/Application</directory>
    <exclude>
      <directory>
         ../src/Application/*/Resources
      </directory>
      <directory>
         ../src/Application/*/Tests
      </directory>
    </exclude>
  </whitelist>
</filter>
Application/
  HelloBundle/
    Model/
      Article.php
    Tests/
      Model/
        ArticleTest.php


    Application/Tests/Model/ArticleTest.php
$ phpunit –c hello/
$ cd hello/
$ phpunit
$ phpunit -c hello/ src/Application/HelloBundle/

$ phpunit -c hello/ src/Application/HelloBundle/
Tests/Controller/HelloControllerTest.php
$ cd hello/
$ phpunit --coverage-html=cov/
Standard artifacts


--coverage-clover=clover.xml

--log-junit=junit.xml
Functional Tests
Do not write Unit Tests for a Controller
namespace ApplicationHelloBundleTestsController;

use SymfonyFrameworkWebBundleTestWebTestCase;

class HelloControllerTest extends WebTestCase
{
  public function testIndex()
  {
    $client = $this->createClient();
    $crawler = $client->request(
      'GET', '/hello/Fabien');

        $this->assertTrue($crawler->filter(
          'html:contains("Hello Fabien")')->count());
    }
}
$client = $this->createClient();

$crawler = $client->request(
  'GET', '/hello/Fabien');

$this->assertTrue($crawler->filter(
  'html:contains("Hello Fabien")')->count());
Environment   Debug mode
$this->createClient('test', true);
# hello/config/config_test.yml
imports:
    - { resource: config_dev.yml }

web.config:
    toolbar: false

zend.logger:
    priority: debug

kernel.test: ~
The Client makes requests to the Symfony2 application



 The Crawler parses the Response to allow navigation



     The PHPUnit Assertions tests the Response
Assertions
$this->assertEquals(
  10,
  $crawler->filter('div.hentry')->count());

$this->assertTrue(
  $client->getResponse()->isSuccessful());
The Client / The Crawler
$crawler = $client->request(
   'GET', 'hello/Lucas'
);
$link = $crawler->selectLink("Greet Lucas");

$client->click($link);
$form = $crawler->selectButton('submit');

$client->submit($form, array(
    'name'         => 'Lucas',
    'country'      => 'France',
    'like_symfony' => true,
    'photo'        => '/path/to/lucas.jpg',
));
$harry = $this->createClient();
$sally = $this->createClient();

$harry->request('POST', '/say/sally/Hello');
$sally->request('GET', '/messages');

$this->assertEquals(201,
  $harry->getResponse()->getStatusCode());

$this->assertRegExp('/Hello/',
  $sally->getResponse()->getContent());
$harry = $this->createClient();
$sally = $this->createClient();

$harry->insulate();
$sally->insulate();

$harry->request('POST', '/say/sally/Hello');
$sally->request('GET', '/messages');

$this->assertEquals(201,
  $harry->getResponse()->getStatusCode());
$this->assertRegExp('/Hello/',
  $sally->getResponse()->getContent());
Main PHP Process

1                                            4
$harry = $this->createClient();                $this->assertEquals(201,
$sally = $this->createClient();                         $harry->getResponse()->getStatusCode());
                                               $this-­‐>assertRegExp('/Hello/',	
  
$harry->insulate();                            	
  	
  $sally-­‐>getResponse()-­‐>getContent());	
  
$sally->insulate();




                       2
                                               Forked PHP Process
                           $harry->request('POST', '/say/sally/Hello');


                       3
                                               Forked PHP Process
                           $sally-­‐>request('GET',	
  '/messages');
Main PHP Process

1                                        3
$harry = $this->createClient();              $sally->request('GET', '/messages');
$sally = $this->createClient();
                                             $this->assertEquals(201,
$harry->insulate();                                   $harry->getResponse()->getStatusCode());
                                             $this-­‐>assertRegExp('/Hello/',	
  
                                             	
  	
  $sally-­‐>getResponse()-­‐>getContent());	
  



                       2
                                         Forked PHP Process
                           $harry->request('POST', '/say/sally/Hello');
Simulate or use HTTP
$response = $client->getResponse();
$profiler = $this->getProfiler($response);

if ($profiler) {
  $this->assertEquals(2,
    $profiler['db']->getQueryCount());

    $this->assertEquals('blog_post',
      $profiler['app']->getRoute());

    $this->assertTrue(
      $profiler['timer']->getTime() < 0.5);
}
Questions?
Sensio S.A.
   92-98, boulevard Victor Hugo
       92 115 Clichy Cedex
             FRANCE
      Tél. : +33 1 40 99 80 80

              Contact
          Fabien Potencier
   fabien.potencier at sensio.com


  http://www.sensiolabs.com/
http://www.symfony-project.org/
 http://fabien.potencier.org/

Unit and Functional Testing with Symfony2