Symfony2 - Jobeet - Jour 09 - Les tests fonctionnels

1 1 1 1 1 1 1 1 1 1 Rating 0.00 (0 Votes)
Submit to DeliciousSubmit to DiggSubmit to FacebookSubmit to Google PlusSubmit to StumbleuponSubmit to TechnoratiSubmit to TwitterSubmit to LinkedIn

Les tests fonctionnels sont un excellent outil pour tester votre application d'un bout à l'autre : de la demande faite par un navigateur jusqu'à la réponse envoyée par le serveur. Ils testent toutes les couches d'une application : le routage, le modèle, les actions et les templates. Ils sont très similaires à ce que vous avez probablement déjà fait manuellement: chaque fois que vous ajoutez ou modifiez une action, vous devez aller dans le navigateur et vérifier que tout fonctionne comme prévu en cliquant sur les liens et vérifier les éléments sur la page rendue. En d'autres termes, vous exécutez un scénario correspondant au cas d'utilisation que vous venez de mettre en œuvre.

Comme le processus est manuel, il est fastidieux et source d'erreurs. Chaque fois que vous changez quelque chose dans votre code, vous devez faire défiler tous les scénarios pour vérifier que vous n'avez rien cassé. C'est de la folie. Les tests fonctionnels dans Symfony fournissent un moyen facile de décrire des scénarios. Chaque scénario peut alors être automatiquement lu maintes et maintes fois en simulant l'expérience d'un utilisateur dans un navigateur. Comme les tests unitaires, ils vous donnent l'assurance nécessaire pour coder en paix.

Les tests fonctionnels ont un flux de travail très spécifique :

  • Faire une demande ;
  • Tester la réponse ;
  • Cliquer sur un lien ou remplir un formulaire ;
  • Tester la réponse ;
  • Nettoyer et répéter.

Notre premier test fonctionnel

Les tests fonctionnels sont de simples fichiers PHP qui habituellement se situent dans le répertoire Tests/Controller de votre paquet. Si vous voulez tester les pages traitées par votre classe CategoryController, commencez par créer un fichier CategoryControllerTest.php qui étend une classe spéciale WebTestCase :

  •  src/Erlem/JobeetBundle/Tests/Controller/CategoryControllerTest.php
<?php

namespace Erlem\JobeetBundle\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Input\ArrayInput;
use Doctrine\Bundle\DoctrineBundle\Command\DropDatabaseDoctrineCommand;
use Doctrine\Bundle\DoctrineBundle\Command\CreateDatabaseDoctrineCommand;
use Doctrine\Bundle\DoctrineBundle\Command\Proxy\CreateSchemaDoctrineCommand;

class CategoryControllerTest extends WebTestCase
{
    private $em;
    private $application;

    public function setUp()
    {
        static::$kernel = static::createKernel();
        static::$kernel->boot();

        $this->application = new Application(static::$kernel);

        // drop the database
        $command = new DropDatabaseDoctrineCommand();
        $this->application->add($command);
        $input = new ArrayInput(array(
            'command' => 'doctrine:database:drop',
            '--force' => true
        ));
        $command->run($input, new NullOutput());

        // we have to close the connection after dropping the database so we don't get "No database selected" error
        $connection = $this->application->getKernel()->getContainer()->get('doctrine')->getConnection();
        if ($connection->isConnected()) {
            $connection->close();
        }

        // create the database
        $command = new CreateDatabaseDoctrineCommand();
        $this->application->add($command);
        $input = new ArrayInput(array(
            'command' => 'doctrine:database:create',
        ));
        $command->run($input, new NullOutput());

        // create schema
        $command = new CreateSchemaDoctrineCommand();
        $this->application->add($command);
        $input = new ArrayInput(array(
            'command' => 'doctrine:schema:create',
        ));
        $command->run($input, new NullOutput());

        // get the Entity Manager
        $this->em = static::$kernel->getContainer()
            ->get('doctrine')
            ->getManager();

        // load fixtures
        $client = static::createClient();
        $loader = new \Symfony\Bridge\Doctrine\DataFixtures\ContainerAwareLoader($client->getContainer());
        $loader->loadFromDirectory(static::$kernel->locateResource('@ErlemJobeetBundle/DataFixtures/ORM'));
        $purger = new \Doctrine\Common\DataFixtures\Purger\ORMPurger($this->em);
        $executor = new \Doctrine\Common\DataFixtures\Executor\ORMExecutor($this->em, $purger);
        $executor->execute($loader->getFixtures());
    }

    public function testShow()
    {
        $client = static::createClient();

        $crawler = $client->request('GET', '/category/index');
        $this->assertEquals('Erlem\JobeetBundle\Controller\CategoryController::showAction', $client->getRequest()->attributes->get('_controller'));
        $this->assertTrue(200 === $client->getResponse()->getStatusCode());
    }
}

Pour en savoir plus sur crawler, lisez la documentation Symfony ici.

Exécution des tests fonctionnels

Comme pour les tests unitaires, le lancement des tests fonctionnels peut être fait en exécutant la commande phpunit :

phpunit -c app/ src/Erlem/JobeetBundle/Tests/Controller/CategoryControllerTest

Ce test va échouer parce que l'URL testée, /category/index, n'est pas une URL valide dans Jobeet :

PHPUnit 4.0.17 by Sebastian Bergmann.

Configuration read from /home/debian/www/jobeet/app/phpunit.xml.dist

F

Time: 11.63 seconds, Memory: 56.00Mb

There was 1 failure:

1) Erlem\JobeetBundle\Tests\Controller\CategoryControllerTest::testShow
Failed asserting that false is true.

/home/debian/www/jobeet/src/Erlem/JobeetBundle/Tests/Controller/CategoryControllerTest.php:76
                                     
FAILURES!                            
Tests: 1, Assertions: 2, Failures: 1.

Écriture des tests fonctionnels

Écrire des tests fonctionnels, c'est comme jouer un scénario dans un navigateur. Nous avons déjà écrit tous les scénarios que nous avons besoin de tester dans le cadre du deuxième jour.

Tout d'abord, nous allons tester la page d'accueil Jobeet en modifiant le fichier de test JobControllerTest.php. Remplacez le code par le suivant :

LES OFFRES EXPIRÉES NE SONT PAS LISTÉES

  • src/Erlem/JobeetBundle/Test/Controller/JobControllerTest.php
<?php

namespace Erlem\JobeetBundle\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Input\ArrayInput;
use Doctrine\Bundle\DoctrineBundle\Command\DropDatabaseDoctrineCommand;
use Doctrine\Bundle\DoctrineBundle\Command\CreateDatabaseDoctrineCommand;
use Doctrine\Bundle\DoctrineBundle\Command\Proxy\CreateSchemaDoctrineCommand;

class JobControllerTest extends WebTestCase
{
    private $em;
    private $application;

    public function setUp()
    {
        static::$kernel = static::createKernel();
        static::$kernel->boot();

        $this->application = new Application(static::$kernel);

        // drop the database
        $command = new DropDatabaseDoctrineCommand();
        $this->application->add($command);
        $input = new ArrayInput(array(
            'command' => 'doctrine:database:drop',
            '--force' => true
        ));
        $command->run($input, new NullOutput());

        // we have to close the connection after dropping the database so we don't get "No database selected" error
        $connection = $this->application->getKernel()->getContainer()->get('doctrine')->getConnection();
        if ($connection->isConnected()) {
            $connection->close();
        }

        // create the database
        $command = new CreateDatabaseDoctrineCommand();
        $this->application->add($command);
        $input = new ArrayInput(array(
            'command' => 'doctrine:database:create',
        ));
        $command->run($input, new NullOutput());

        // create schema
        $command = new CreateSchemaDoctrineCommand();
        $this->application->add($command);
        $input = new ArrayInput(array(
            'command' => 'doctrine:schema:create',
        ));
        $command->run($input, new NullOutput());

        // get the Entity Manager
        $this->em = static::$kernel->getContainer()
            ->get('doctrine')
            ->getManager();

        // load fixtures
        $client = static::createClient();
        $loader = new \Symfony\Bridge\Doctrine\DataFixtures\ContainerAwareLoader($client->getContainer());
        $loader->loadFromDirectory(static::$kernel->locateResource('@ErlemJobeetBundle/DataFixtures/ORM'));
        $purger = new \Doctrine\Common\DataFixtures\Purger\ORMPurger($this->em);
        $executor = new \Doctrine\Common\DataFixtures\Executor\ORMExecutor($this->em, $purger);
        $executor->execute($loader->getFixtures());
    }

    public function testIndex()
    {
        $client = static::createClient();
        $crawler = $client->request('GET', '/');

        $this->assertEquals('Erlem\JobeetBundle\Controller\JobController::indexAction', $client->getRequest()->attributes->get('_controller'));
        $this->assertTrue($crawler->filter('.jobs td.position:contains("Expired")')->count() == 0);
    }
}

Pour vérifier l'exclusion des offres expirées depuis la page d'accueil, nous vérifions que le sélecteur CSS .jobs td.position:contains("Expired") ne correspond à rien dans le contenu de la réponse HTML (rappelons que dans les fixtures, la seule offre expirée contient "Expired" dans l'intitulé).

SEULEMENT N OFFRES SONT AFFICHÉES POUR UNE CATÉGORIE

Ajoutez le code suivant à la fin du fichier de test. Pour obtenir le paramètre personnalisé défini dans app/config/config.yml dans notre test fonctionnel, nous allons utiliser le noyau :

  • src/Erlem/JobeetBundle/Test/Controller/JobControllerTest.php
public function testIndex()
{
    //...
    $kernel = static::createKernel();
    $kernel->boot();
    $max_jobs_on_homepage = $kernel->getContainer()->getParameter('max_jobs_on_homepage');
    $this->assertTrue($crawler->filter('.category_programming tr')->count() <= $max_jobs_on_homepage );
}

Pour que ce test fonctionne, nous aurons besoin d'ajouter la classe CSS correspondant à chaque catégorie dans le fichier Job/index.html.twig (afin que nous puissions sélectionner chaque catégorie et compter les offres répertoriées) :

  •  src/Erlem/JobeetBundle/Resources/views/Job/index.html.twig
<!-- ... -->

    {% for category in categories %}
        <div class="category_{{ category.slug }}">
           <div class="category">
<!-- ... -->

UNE CATÉGORIE A UN LIEN VERS LA PAGE CATÉGORIE SEULEMENT S'IL Y A TROP D'OFFRES

  • src/Erlem/JobeetBundle/Test/Controller/JobControllerTest.php
public function testIndex()
{
    //...
    $this->assertTrue($crawler->filter('.category_design .more_jobs')->count() == 0);
    $this->assertTrue($crawler->filter('.category_programming .more_jobs')->count() == 1);
}

Dans ces tests, nous vérifions qu'il n'y a pas de "plus d'offres" pour la catégorie Design (.category_design .more_jobs n'existe pas), et qu'il y a un "plus d'offres" pour la catégorie Programming (.category_programming .more_jobs existe ).

LES OFFRES SONT TRIÉES PAR DATE

Pour tester si les offres sont effectivement triées par date, nous devons vérifier que le premier emploi figurant sur la page d'accueil est celui que nous attendons. Cela peut être fait en vérifiant que l'URL contient la clé primaire attendue. Comme la clé primaire peut changer entre les exécutions, nous avons besoin de l'objet Doctrine de la BDD en premier.

  •  src/Erlem/JobeetBundle/Test/Controller/JobControllerTest.php
public function testIndex()
{    
    // ...
    $em = $kernel->getContainer()->get('doctrine.orm.entity_manager');

    $query = $em->createQuery('SELECT j from ErlemJobeetBundle:Job j LEFT JOIN j.category c WHERE c.slug = :slug AND j.expires_at > :date ORDER BY j.created_at DESC');
    $query->setParameter('slug', 'programming');
    $query->setParameter('date', date('Y-m-d H:i:s', time()));
    $query->setMaxResults(1);
    $job = $query->getSingleResult();

    $this->assertTrue($crawler->filter('.category_programming tr')->first()->filter(sprintf('a[href*="/%d/"]', $job->getId()))->count() == 1);
}

Même si le test fonctionne tel quel, nous avons besoin de factoriser le code un peu, car l'obtention de la première offre de la catégorie Programming peut être réutilisée ailleurs dans nos tests. Nous ne bougerons pas le code vers la couche Modèle puisque le code est spécifique au test. Au lieu de cela, nous allons déplacer le code de la fonction getMostRecentProgrammingJob() dans notre classe de test :

  •  src/Erlem/JobeetBundle/Test/Controller/JobControllerTest.php
// ...

    public function getMostRecentProgrammingJob()
    {
        $kernel = static::createKernel();
        $kernel->boot();
        $em = $kernel->getContainer()->get('doctrine.orm.entity_manager');

        $query = $em->createQuery('SELECT j from ErlemJobeetBundle:Job j LEFT JOIN j.category c WHERE c.slug = :slug AND j.expires_at > :date ORDER BY j.created_at DESC');
        $query->setParameter('slug', 'programming');
        $query->setParameter('date', date('Y-m-d H:i:s', time()));
        $query->setMaxResults(1);

        return $query->getSingleResult();
    }

// ...

Vous pouvez maintenant remplacer le code de test précédent par le suivant :

  •  src/Erlem/JobeetBundle/Test/Controller/JobControllerTest.php
// ...

$this->assertTrue($crawler->filter('.category_programming tr')->first()->filter(sprintf('a[href*="/%d/"]', $this->getMostRecentProgrammingJob()->getId()))->count() == 1);

//...

CHAQUE OFFRE SUR LA PAGE D'ACCUEIL EST CLIQUABLE

Pour tester le lien d'offre sur le site, nous simulons un clic sur le texte "Web Developer". Comme il y a beaucoup d'entre eux sur la page, nous avons explicitement demandé au navigateur de cliquer sur la première.

Chaque paramètre de requête est ensuite testé pour s'assurer que le routage a fait son travail correctement.

  •  src/Erlem/JobeetBundle/Test/Controller/JobControllerTest.php
public function testIndex() 
{
    // ...

    $job = $this->getMostRecentProgrammingJob();
    $link = $crawler->selectLink('Web Developer')->first()->link();
    $crawler = $client->click($link);
    $this->assertEquals('Erlem\JobeetBundle\Controller\JobController::showAction', $client->getRequest()->attributes->get('_controller'));
    $this->assertEquals($job->getCompanySlug(), $client->getRequest()->attributes->get('company'));
    $this->assertEquals($job->getLocationSlug(), $client->getRequest()->attributes->get('location'));
    $this->assertEquals($job->getPositionSlug(), $client->getRequest()->attributes->get('position'));
    $this->assertEquals($job->getId(), $client->getRequest()->attributes->get('id'));
}

// ...

APPRENEZ PAR L'EXEMPLE

Dans cette section, vous avez tout le code nécessaire pour tester les pages offre et catégorie. Lisez le code avec soin car vous apprendrez quelques nouveaux trucs :

  •  src/Erlem/JobeetBundle/Test/Controller/JobControllerTest.php
<?php

namespace Erlem\JobeetBundle\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Input\ArrayInput;
use Doctrine\Bundle\DoctrineBundle\Command\DropDatabaseDoctrineCommand;
use Doctrine\Bundle\DoctrineBundle\Command\CreateDatabaseDoctrineCommand;
use Doctrine\Bundle\DoctrineBundle\Command\Proxy\CreateSchemaDoctrineCommand;

class JobControllerTest extends WebTestCase
{
    private $em;
    private $application;

    public function setUp()
    {
        static::$kernel = static::createKernel();
        static::$kernel->boot();

        $this->application = new Application(static::$kernel);

        // drop the database
        $command = new DropDatabaseDoctrineCommand();
        $this->application->add($command);
        $input = new ArrayInput(array(
            'command' => 'doctrine:database:drop',
            '--force' => true
        ));
        $command->run($input, new NullOutput());

        // we have to close the connection after dropping the database so we don't get "No database selected" error
        $connection = $this->application->getKernel()->getContainer()->get('doctrine')->getConnection();
        if ($connection->isConnected()) {
            $connection->close();
        }

        // create the database
        $command = new CreateDatabaseDoctrineCommand();
        $this->application->add($command);
        $input = new ArrayInput(array(
            'command' => 'doctrine:database:create',
        ));
        $command->run($input, new NullOutput());

        // create schema
        $command = new CreateSchemaDoctrineCommand();
        $this->application->add($command);
        $input = new ArrayInput(array(
            'command' => 'doctrine:schema:create',
        ));
        $command->run($input, new NullOutput());

        // get the Entity Manager
        $this->em = static::$kernel->getContainer()
            ->get('doctrine')
            ->getManager();

        // load fixtures
        $client = static::createClient();
        $loader = new \Symfony\Bridge\Doctrine\DataFixtures\ContainerAwareLoader($client->getContainer());
        $loader->loadFromDirectory(static::$kernel->locateResource('@ErlemJobeetBundle/DataFixtures/ORM'));
        $purger = new \Doctrine\Common\DataFixtures\Purger\ORMPurger($this->em);
        $executor = new \Doctrine\Common\DataFixtures\Executor\ORMExecutor($this->em, $purger);
        $executor->execute($loader->getFixtures());
    }

    public function getMostRecentProgrammingJob()
    {
        $kernel = static::createKernel();
        $kernel->boot();
        $em = $kernel->getContainer()->get('doctrine.orm.entity_manager');

        $query = $em->createQuery('SELECT j from ErlemJobeetBundle:Job j LEFT JOIN j.category c WHERE c.slug = :slug AND j.expires_at > :date ORDER BY j.created_at DESC');
        $query->setParameter('slug', 'programming');
        $query->setParameter('date', date('Y-m-d H:i:s', time()));
        $query->setMaxResults(1);

        return $query->getSingleResult();
    }

    public function getExpiredJob()
    {
        $kernel = static::createKernel();
        $kernel->boot();
        $em = $kernel->getContainer()->get('doctrine.orm.entity_manager');

        $query = $em->createQuery('SELECT j from ErlemJobeetBundle:Job j WHERE j.expires_at < :date');             
        $query->setParameter('date', date('Y-m-d H:i:s', time()));
        $query->setMaxResults(1);

        return $query->getSingleResult();
    }

    public function testIndex()
    {
        // get the custom parameters from app config.yml
        $kernel = static::createKernel();
        $kernel->boot();
        $max_jobs_on_homepage = $kernel->getContainer()->getParameter('max_jobs_on_homepage');

        $client = static::createClient();

        $crawler = $client->request('GET', '/');
        $this->assertEquals('Erlem\JobeetBundle\Controller\JobController::indexAction', $client->getRequest()->attributes->get('_controller'));

        // expired jobs are not listed
        $this->assertTrue($crawler->filter('.jobs td.position:contains("Expired")')->count() == 0);

        // only $max_jobs_on_homepage jobs are listed for a category
        $this->assertTrue($crawler->filter('.category_programming tr')->count()<= $max_jobs_on_homepage); 
        $this->assertTrue($crawler->filter('.category_design .more_jobs')->count() == 0);
        $this->assertTrue($crawler->filter('.category_programming .more_jobs')->count() == 1);

        // jobs are sorted by date
        $this->assertTrue($crawler->filter('.category_programming tr')->first()->filter(sprintf('a[href*="/%d/"]', $this->getMostRecentProgrammingJob()->getId()))->count() == 1);

        // each job on the homepage is clickable and give detailed information
        $job = $this->getMostRecentProgrammingJob();
        $link = $crawler->selectLink('Web Developer')->first()->link();
        $crawler = $client->click($link);
        $this->assertEquals('Erlem\JobeetBundle\Controller\JobController::showAction', $client->getRequest()->attributes->get('_controller'));
        $this->assertEquals($job->getCompanySlug(), $client->getRequest()->attributes->get('company'));
        $this->assertEquals($job->getLocationSlug(), $client->getRequest()->attributes->get('location'));
        $this->assertEquals($job->getPositionSlug(), $client->getRequest()->attributes->get('position'));
        $this->assertEquals($job->getId(), $client->getRequest()->attributes->get('id'));

        // a non-existent job forwards the user to a 404
        $crawler = $client->request('GET', '/job/foo-inc/milano-italy/0/painter');
        $this->assertTrue(404 === $client->getResponse()->getStatusCode());

        // an expired job page forwards the user to a 404
        $crawler = $client->request('GET', sprintf('/job/sensio-labs/paris-france/%d/web-developer', $this->getExpiredJob()->getId()));
        $this->assertTrue(404 === $client->getResponse()->getStatusCode());
    }
}
  • src/Erlem/JobeetBundle/Test/Controller/CategoryControllerTest.php
<?php

namespace Erlem\JobeetBundle\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Input\ArrayInput;
use Doctrine\Bundle\DoctrineBundle\Command\DropDatabaseDoctrineCommand;
use Doctrine\Bundle\DoctrineBundle\Command\CreateDatabaseDoctrineCommand;
use Doctrine\Bundle\DoctrineBundle\Command\Proxy\CreateSchemaDoctrineCommand;

class CategoryControllerTest extends WebTestCase
{
    private $em;
    private $application;
    public function setUp()
    {
        static::$kernel = static::createKernel();
        static::$kernel->boot();

        $this->application = new Application(static::$kernel);

        // drop the database
        $command = new DropDatabaseDoctrineCommand();
        $this->application->add($command);
        $input = new ArrayInput(array(
            'command' => 'doctrine:database:drop',
            '--force' => true
        ));
        $command->run($input, new NullOutput());

        // we have to close the connection after dropping the database so we don't get "No database selected" error
        $connection = $this->application->getKernel()->getContainer()->get('doctrine')->getConnection();
        if ($connection->isConnected()) {
            $connection->close();
        }

        // create the database
        $command = new CreateDatabaseDoctrineCommand();
        $this->application->add($command);
        $input = new ArrayInput(array(
            'command' => 'doctrine:database:create',
        ));
        $command->run($input, new NullOutput());

        // create schema
        $command = new CreateSchemaDoctrineCommand();
        $this->application->add($command);
        $input = new ArrayInput(array(
            'command' => 'doctrine:schema:create',
        ));
        $command->run($input, new NullOutput());

        // get the Entity Manager
        $this->em = static::$kernel->getContainer()
            ->get('doctrine')
            ->getManager();

        // load fixtures
        $client = static::createClient();
        $loader = new \Symfony\Bridge\Doctrine\DataFixtures\ContainerAwareLoader($client->getContainer());
        $loader->loadFromDirectory(static::$kernel->locateResource('@ErlemJobeetBundle/DataFixtures/ORM'));
        $purger = new \Doctrine\Common\DataFixtures\Purger\ORMPurger($this->em);
        $executor = new \Doctrine\Common\DataFixtures\Executor\ORMExecutor($this->em, $purger);
        $executor->execute($loader->getFixtures());
    }

    public function testShow()
    {
        $kernel = static::createKernel();
        $kernel->boot();

        // get the custom parameters from app/config.yml
        $max_jobs_on_category = $kernel->getContainer()->getParameter('max_jobs_on_category');
        $max_jobs_on_homepage = $kernel->getContainer()->getParameter('max_jobs_on_homepage');

        $client = static::createClient();

        $categories = $this->em->getRepository('ErlemJobeetBundle:Category')->getWithJobs();

        // categories on homepage are clickable
        foreach($categories as $category) {
            $crawler = $client->request('GET', '/');

            $link = $crawler->selectLink($category->getName())->link();
            $crawler = $client->click($link);

            $this->assertEquals('Erlem\JobeetBundle\Controller\CategoryController::showAction', $client->getRequest()->attributes->get('_controller'));
            $this->assertEquals($category->getSlug(), $client->getRequest()->attributes->get('slug'));

            $jobs_no = $this->em->getRepository('ErlemJobeetBundle:Job')->countActiveJobs($category->getId()); 

            // categories with more than $max_jobs_on_homepage jobs also have a "more" link                 
            if($jobs_no > $max_jobs_on_homepage) {
                $crawler = $client->request('GET', '/');
                $link = $crawler->filter(".category_" . $category->getSlug() . " .more_jobs a")->link();
                $crawler = $client->click($link);

                $this->assertEquals('Erlem\JobeetBundle\Controller\CategoryController::showAction', $client->getRequest()->attributes->get('_controller'));
                $this->assertEquals($category->getSlug(), $client->getRequest()->attributes->get('slug'));
            }

            $pages = ceil($jobs_no/$max_jobs_on_category);

            // only $max_jobs_on_category jobs are listed 
            $this->assertTrue($crawler->filter('.jobs tr')->count() <= $max_jobs_on_category);
            $this->assertRegExp("/" . $jobs_no . " jobs/", $crawler->filter('.pagination_desc')->text());

            if($pages > 1) {
                $this->assertRegExp("/page 1\/" . $pages . "/", $crawler->filter('.pagination_desc')->text());

                for ($i = 2; $i <= $pages; $i++) {
                    $link = $crawler->selectLink($i)->link();
                    $crawler = $client->click($link);

                    $this->assertEquals('Erlem\JobeetBundle\Controller\CategoryController::showAction', $client->getRequest()->attributes->get('_controller'));
                    $this->assertEquals($i, $client->getRequest()->attributes->get('page'));
                    $this->assertTrue($crawler->filter('.jobs tr')->count() <= $max_jobs_on_category);
                    if($jobs_no >1) {
                        $this->assertRegExp("/" . $jobs_no . " jobs/", $crawler->filter('.pagination_desc')->text());
                    }
                    $this->assertRegExp("/page " . $i . "\/" . $pages . "/", $crawler->filter('.pagination_desc')->text());
                }
            }     
        }
    }
}

Ensuite exécutez les commandes ci-dessous :

Pour JobController :

phpunit -c app/ src/Erlem/JobeetBundle/Tests/Controller/JobControllerTest

Le résultat :

PHPUnit 4.0.17 by Sebastian Bergmann.

Configuration read from /home/debian/www/jobeet/app/phpunit.xml.dist

.

Time: 4.43 seconds, Memory: 60.75Mb

OK (1 test, 13 assertions)

Pour CategoryController :

phpunit -c app/ src/Erlem/JobeetBundle/Tests/Controller/CategoryControllerTest

Le résultat :

PHPUnit 4.0.17 by Sebastian Bergmann.

Configuration read from /home/debian/www/jobeet/app/phpunit.xml.dist

.

Time: 3.5 seconds, Memory: 18.00Mb

OK (1 test, 16 assertions)

Pour visualiser la couverture de code :

phpunit --coverage-html=web/cov/ -c app src/Erlem/JobeetBundle/Tests/

Ensuite allez à l'adresse http://jobeet.local/cov/Controller/index.html pour voir les contrôleurs. 

01-108-symfony2-jobeet-jour-09-les-tests-fonctionnels

Et plus précisément à http://jobeet.local/cov/Controller/CategoryController.php.html pour CategoryController.

02-108-symfony2-jobeet-jour-09-les-tests-fonctionnels

Et http://jobeet.local/cov/Controller/JobController.php.html pour JobController.

03-108-symfony2-jobeet-jour-09-les-tests-fonctionnels

C'est fini pour aujourd'hui ! Demain, nous allons apprendre ce que l'on doit savoir sur les formulaires.

Code source

Le code source est sur GitHub. Vous pouvez le télécharger en exécutant les commandes ci-dessous (prérequis Symfony2 - Jobeet - Jour 01 - Démarrage du projet) :

su
cd /var/www/
git clone https://github.com/erlem/jobeet.git
cd jobeet/
git checkout tags/v0.9.0
 
composer update
 
php app/console doctrine:database:create
php app/console doctrine:schema:update --force
php app/console doctrine:fixtures:load
 
php app/console assets:install web

chmod 777 -R app/cache/
chmod 777 -R app/logs/

Vous pouvez maintenant tester l'application dans un navigateur: http://jobeet.local/ ou dans l'environnement de développement, http://jobeet.local/app_dev.php.


Symfony2 - Jour 08 - Les tests unitaires
[Sommaire] Symfony2 - Jour 10 - Les formulaires >


Pour ce tutoriel, je me suis inspiré du tutoriel Symfony2 Jobeet du site IntelligentBee

Submit to DeliciousSubmit to DiggSubmit to FacebookSubmit to Google PlusSubmit to StumbleuponSubmit to TechnoratiSubmit to TwitterSubmit to LinkedIn