Je suis développeur web freelance et propose des formations à Symfony2 ! Contactez-moi pour en discuter.

Cet article est la traduction d’un article original de Fabien Potencier, à l’origine de Symfony2, disponible ici.

Des lecteurs vigilants ont fait remarquer des bugs subtils mais non moins importants dans le framework que nous avons construit hier. Lorsque l’on crée un framework, il faut être certain qu’il se comporte comme annoncé. Si ce n’est pas le cas, toutes les applications basées dessus souffriront des mêmes bugs. La bonne nouvelle, c’est que quand on corrige un bug, on le corrige dans plusieurs applications à la fois.

La mission du jour est d’écrire des tests unitaire pour le framework que nous avons créé en utilisant PHPUnit. Créez un fichier de configuration de PHPUnit dans example.com/phpunit.xml.dist :




./tests



Cette configuration définit définit des valeurs par défaut pour la plupart des paramètres PHPUnit; plus intéressant, l’autoloader est utilisé pour bootstrapper les tests, et les tests seront stockés dans le répertoire example.com/tests/.

Maintenant, écrivons un test pour les ressources « Non trouvées ». Pour éviter la création de dépendances lorsque l’on écrit des tests et pour ne réellement tester unitairement que ce qui nous intéresse, nous allons utiliser des objets mocks. Les objets mocks sont plus faciles à créer lorsque l’on utilise des interfaces plutôt que des classes concrètes. Heureusement, Symfony2 nous fournit de telles interfaces pour pour les objets du coeur de la librairie, tel que UrlMatcher et le résolveur de contrôleurs. Modifiez le framework pour vous en servir :


matcher = $matcher;
$this->resolver = $resolver;
}

// ...
}

Nous sommes maintenant prêts pour écrire notre premier test :


getFrameworkForException(new ResourceNotFoundException());

$response = $framework->handle(new Request());

$this->assertEquals(404, $response->getStatusCode());
}

protected function getFrameworkForException($exception)
{
$matcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface');
$matcher
->expects($this->once())
->method('match')
->will($this->throwException($exception))
;
$resolver = $this->getMock('Symfony\Component\HttpKernel\Controller\ControllerResolverInterface');

return new Framework($matcher, $resolver);
}
}

Ce test simule une requête qui n’est associé à aucune route. De ce fait, la méthode match() renvoit une exception ResourceNotFoundException et nous testons que le framework convertit bien cette exception en une réponse 404.

Pour exécuter ce test, il suffit de lancer la commande « phpunit » depuis le répertoire example.com :

$ phpunit

Je n’explique pas en détail comment fonctionne le code car ce n’est pas le but de cette série, mais si vous ne comprenez rien de ce qui se passe, je vous suggère de lire la documentation de PHPUnit sur les objets mocks.

Une fois le test exécuté, vous devriez voir une barre verte. Si ce n’est pas le cas, il y a un bug soit dans le test ou dans le code du framework !

Ajouter un test unitaire pour n’importe quelle exception lancée dans un contrôlleur est tout aussi simple :


public function testErrorHandling()
{
$framework = $this->getFrameworkForException(new \RuntimeException());

$response = $framework->handle(new Request());

$this->assertEquals(500, $response->getStatusCode());
}


Et pour finir, écrivons un test pour une situation où il ne doit pas y avoir d’erreurs :


use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Controller\ControllerResolver;

public function testControllerResponse()
{
$matcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface');
$matcher
->expects($this->once())
->method('match')
->will($this->returnValue(array(
'_route' => 'foo',
'name' => 'Fabien',
'_controller' => function ($name) {
return new Response('Hello '.$name);
}
)))
;
$resolver = new ControllerResolver();

$framework = new Framework($matcher, $resolver);

$response = $framework->handle(new Request());

$this->assertEquals(200, $response->getStatusCode());
$this->assertContains('Hello Fabien', $response->getContent());
}

Dans ce test, on simule une route correctement associé qui renvoit un contrôlleur simple. On vérifie que le status de la réponse est 200 et que son contenu est celui défini dans le contrôleur.

Pour vérifier que nous avons bien couvert tous les cas d’utilisation, lancez la fonctionnalité de couverture de code de PHPUnit (il faut activer « XDebug » (http://xdebug.org/) d’abord):

$ phpunit --coverage-html=cov/

Ouvrez example.com/cov/src_Simplex_Framework.php.html dans un navigateur et vérifiez que toutes les lignes de la classe du framework sont vertes (cela signifie qu’elles ont été visitées lorsque le test a été exécuté).

Grâce au code orienté objet simple que nous avons écrit jusque là, nous avons pû écrire des tests unitaires qui couvrent tous les cas d’utilisation possibles de notre framework; Les objets mocks nous ont permis de vérifier que nous testions bien notre code et pas celui de Symfony2.

Maintenant que nous avons (à nouveau) confiance dans le code que nous avons écrit, nous pouvons penser l’esprit tranquille au nouveau jeu de fonctionnalités que nous allons ajouter à notre framework.

Répondre

Unable to load the Are You a Human PlayThru™. Please contact the site owner to report the problem.