Au chapitre précédent, vous avez appris à requêter votre application via un client HTTP. Vous avez la possibilité de récupérer la réponse suite à la requête pour en vérifier le code de statut, par exemple. Vous pouvez en tester les en-têtes également, si cela a lieu d'être.
La prochaine étape est de vérifier que certains éléments sont présents sur la page (par exemple un titre), ou qu'une phrase est présente dans le contenu d'une réponse HTTP.
Inspectez les informations d’une page web avec le crawler
Pour extraire les informations d’une page web, nous pouvons faire appel au “crawler”. Le crawler est un objet auquel vous pouvez accéder après chaque requête, comme suit :
<?php
namespace App\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class DiaryControllerTest extends WebTestCase
{
// …
public function testHomepage()
{
$crawler = $this->client->request(Request::METHOD_GET, $this->urlGenerator->generate('homepage'));
$this->assertSame(
1,
$crawler->filter('html:contains("Bienvenue sur FoodDiary!")')->count()
);
}
}
Comme vous le voyez, à chaque requête nous pouvons récupérer un objet crawler. Il s'agit d'une instance de la classe Symfony\Component\DomCrawler\Crawler
. Après chaque requête, l'objet retourné contient toutes les informations inhérentes au DOM (Document Object Model) de la page.
Pour utiliser les sélecteurs CSS avec le crawler, il faut installer la dépendance suivante :
composer require symfony/css-selector
Dans le code ci-dessus, nous inspectons le contenu de la page (correspondant à la réponse HTTP).
L'instruction $crawler->filter('html:contains("Bienvenue sur FoodDiary !")')->count()
détermine le nombre d'éléments contenus dans la balise html
ayant pour texte "Bienvenue sur FoodDiary".
Il ne nous reste plus ensuite qu'à ajouter une assertion pour nous assurer qu'il n'y a qu'un seul élément avec ces caractéristiques.
Une autre manière de procéder aurait été de trouver l'élément h1 dans la page à l'aide du crawler et de la méthode filter
, comme ceci :
<?php
namespace Tests\AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class DiaryControllerTest extends WebTestCase
{
// …
public function testHomepage()
{
// …
$this->assertSame(1, $crawler->filter('h1')->count());
}
}
Testez un formulaire
Revoyons toutes les étapes de cette vidéo pour vérifier que vous avez bien compris.
En vous baladant dans l'application, vous pouvez remarquer qu'il y a un formulaire pour saisir des entrées dans son journal de bord. Le code pour ce journal de bord est présent dans la classe de contrôleur App\Controller\DiaryController
.
Il est assez simple de comprendre ce qui se trame dans l'action addRecordAction
. La route associée est add-new-record
, et l'URI qu'il faut requêter est la suivante : /diary/add-new-record
.
Soumettez un formulaire
Pour soumettre un formulaire, il faut dans un premier temps requêter la page affichant le formulaire, puis sélectionner le formulaire qui nous intéresse, renseigner les informations nécessaires à la soumission du formulaire et enfin le soumettre.
Voici comment procéder dans le code de nos tests :
<?php
namespace App\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class DiaryControllerTest extends WebTestCase
{
// …
public function testAddRecord()
{
$crawler = $this->client->request(Request::METHOD_GET, $this->urlGenerator->generate('add-new-record'));
$form = $crawler->selectButton('Ajouter')->form();
$form['food[entitled]'] = 'Plat de pâtes';
$form['food[calories]'] = 600;
$this->client->submit($form);
echo $this->client->getResponse()->getContent();
}
}
Affichez le résultat du formulaire
Pour suivre ce qu'il se passe au fur et à mesure que l'on avance dans le code, nous affichons la réponse après la soumission du formulaire.
Lancez la commande suivante :
$ vendor/bin/phpunit --filter=testAddRecord > public/resultTest.html
Sous Windows, utilisez la commande vendor/bin/phpunit
.
Affichons le résultat dans un navigateur :
Cela ne nous arrange pas pour effectuer nos assertions dans notre test…
Ce qui se passe est important à comprendre : en effet, si nous ne demandons pas au client HTTP de suivre les redirections, il restera bloqué à la réponse obtenue après requête.
Il faut donc que nous demandions explicitement au client de suivre la redirection, comme ceci :
<?php
namespace App\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class DiaryControllerTest extends WebTestCase
{
// …
public function testAddRecord()
{
$crawler = $this->client->request(Request::METHOD_GET, $this->urlGenerator->generate('add-new-record'));
$form = $crawler->selectButton('Ajouter')->form();
$form['food[entitled]'] = 'Plat de pâtes';
$form['food[calories]'] = 600;
$this->client->submit($form);
$this->client->followRedirect();
echo $this->client->getResponse()->getContent();
}
}
Notez la ligne $client->followRedirect();
: c'est là que vous demandez au client de suivre la redirection. Relancez la commande précédente.
Désormais, le client suit bien la redirection, ce qui nous permet d'avoir la dernière réponse. Vous allez maintenant pouvoir écrire une assertion pour vérifier que tout s'est bien passé.
Écrivez une assertion
<?php
namespace App\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class DiaryControllerTest extends WebTestCase
{
// …
public function testAddRecord()
{
$crawler = $this->client->request(Request::METHOD_GET, $this->urlGenerator->generate('add-new-record'));
$form = $crawler->selectButton('Ajouter')->form();
$form['food[entitled]'] = 'Plat de pâtes';
$form['food[calories]'] = 600;
$this->client->submit($form);
$this->client->followRedirect();
// Attention à bien récupérer le crawler mis à jour
$this->assertSelectorTextContains('div.alert.alert-success','Une nouvelle entrée dans votre journal a bien été ajoutée');
}
}
Il est également possible de faire en sorte que toutes les redirections soient suivies. Pour cela, il faut ajouter l'instruction suivante juste après la création du client :
<?php
$client->followRedirects();
Ainsi, il est inutile d'ajouter l'instruction $client->followRedirect()
après chaque requête entraînant une redirection.
Exercez-vous en créant un test de plus, en faisant en sorte qu'un ou plusieurs champs soient vides, afin de vérifier les contraintes de validation.
Nous allons installer une autre dépendance afin de ne rien enregistrer en base de données lors de nos tests ; il faudra par la suite modifier un peu notre fichier phpunit.xml.dist.
La commande composer require --dev dama/doctrine-test-bundle
nous permet de ne pas remplir inutilement notre base de données, en faisant un rollback des données enregistrées juste après le test.
Modifions maintenant notre fichier phpunit.xml.dist pour y insérer à la fin les lignes suivantes :
<extensions>
<extension class="DAMA\DoctrineTestBundle\PHPUnit\PHPUnitExtension"/>
</extensions>
Grâce à ces manipulations, la base de données reste “propre”, et nous pouvons tester à volonté sans risquer de casser d’autres tests qui auraient besoin de certains jeux de données.
Cliquez sur un lien pour naviguer vers une autre page
Écrire un test fonctionnel consiste à décrire un scénario utilisateur. Nous pouvons en créer un complet en partant de la page d'accueil, puis simuler un clic sur le lien "Voir tous les rapports", et enfin nous assurer qu'il y a bien le titre H1
"Tous les rapports" :
<?php
namespace App\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class DiaryControllerTest extends WebTestCase
{
// …
public function testList()
{
$crawler = $this->client->request(Request::METHOD_GET, $this->urlGenerator->generate('diary'));
$link = $crawler->selectLink('Voir tous mes rapports')->link();
$crawler = $this->client->click($link);
$info = $crawler->filter('h1')->text();
// On retire les retours à la ligne pour faciliter la vérification
$info = $string = trim(preg_replace('/\s\s+/', ' ', $info));
$this->assertSame("Tous les rapports Tout ce qui a été mangé !", $info);
}
}
À la ligne $link = $crawler->selectLink('Voir tous les rapports')->link();
, on se charge de récupérer l'objet lien pour pouvoir cliquer dessus ensuite (à la ligne $crawler = $client->click($link);
).
En cliquant sur le lien, le navigateur (via le client) est sur la page correspondant à la liste des rapports. Il ne nous reste plus qu'à retrouver l'élément de la page que l'on souhaite tester, et le tour est joué !
Tirez partie du profiler de Symfony
Vous pouvez obtenir bon nombre d'informations, pour corriger vos applications, du profiler de Symfony. Néanmoins, ces informations ne sont visibles que via la “Web Debug Toolbar”, ou encore les pages proposées par le “profiler”.
Alors, comment récupérer ces informations lors de nos tests fonctionnels ?
Depuis l'objet client
créé, il est possible de récupérer le profiler grâce à la méthode getProfile()
.
Pour cela, il faut :
Activer le profiler.
Puis effectuer toutes les actions propres à son scénario de test.
Et enfin, y collecter les informations.
En résumé
Le crawler est un objet qui nous permet de parcourir toute notre page afin de faire nos tests.
Il ne faut pas oublier de l’appeler après chaque redirection, sinon vos données seront faussées.
Attention à ne pas trop utiliser le profiler Symfony, pour garder des tests rapides et légers à l’exécution (principe de base des tests).
C’est bientôt la fin de ce cours ! Dans le prochain chapitre, nous vous proposons de découvrir d’autres librairies avec lesquelles vous pouvez tester votre application. Allez, on y va !