TD5: Tests

Si vous le souhaitez, vous pouvez repartir du dépôt suivant, qui intègre le code des TDs précédents:

Préparation

Test pack

Tout d'abord, installez le test-pack de Symfony :

symfony composer require --dev symfony/test-pack

Base de données

Normalement, la base de données utilisées lors des tests devrait être différente de celle utilisée lors du développement. Cependant, vous n'avez accès au département qu'à une seule base de données, nous avons modifié légèrement le code de geochat de manière à ce que les tables en environnement de test soient préfixées par test_.

Une autre approche consiste en l'utilisation d'une chaîne de connexion différente dans .env.test par exemple.

Pour créer ces tables et les initialiser, lancez :

symfony console --env=test doctrine:schema:update --force
symfony console --env=test doctrine:fixtures:load -n

Note: À ce stade, il se peut que vous ayez besoin d'ajouter l'adresse des messages dans le code de la fixture, car il n'est pas présent dans le code de base.

Réinitialisation de la base de données

Lors de l'exécution des tests, la base de données peut être modifiée. On souhaiterait idéalement que cette dernière soit remise dans le même état à chaque test. Pour cela, installez :

# Ajoute le bundle de test Doctrine
symfony composer require --dev dama/doctrine-test-bundle

Ajoutez ensuite le contenu suivant dans config/packages/doctrine.yaml :

when@test:
    doctrine:
        dbal:
            connections:
                default:
                    use_savepoints: true

Puis ajoutez l'extension suivante dans phpunit.xml.dist :

<!-- phpunit.xml.dist -->
<phpunit>
    <!-- ... -->

    <extensions>
        <extension class="DAMA\DoctrineTestBundle\PHPUnit\PHPUnitExtension"/>
    </extensions>
</phpunit>

Cette extension s'assurera que la base de données est remise dans le même état entre chaque exécution de test.

Écriture de tests

Tests de requêtes

Nous allons tout d'abord écrire des tests portant sur les requêtes faites dans la base de données. Lancez :

symfony console make:test

Et créez un test de type WebTestCase portant le nom MessagesRepositoryTest.

Pour lancez les tests, utilisez la commande :

php bin/phpunit

Vous pourrez obtenir un service, comme le MessageRepository à l'aide du container:

/** @var MessageRepository */
$messageRepository = static::getContainer()->get(MessageRepository::class);

Implémentez une méthode testFindClose() dans la classe générée, qui enverra une requête dans la base (à l'aide de findClose()) pour la longitude -0.57389 et la latitude 44.8451032 dans un rayon de 100 m).

Connaissant le jeu de données (chargées à l'aide de la fixture), on devrait obtenir un seul message (celui exactement présent aux coordonnées fournies). Testez ensuite à l'aide d'assertions que :

  • La requête a donné exactement un résultat,
  • Le texte du message est bien celui attendu,
  • Le résultat est à une distance de 0 (ou presque, aux erreurs numériques près) des coordonnées fournies.

Test de l'API

Ajoutez maintenant une nouvelle classe de test, toujours de type WebTestCase. Nommez-la UserApiTest.

Vous pourrez utiliser le code suivant:

$response = json_decode($client->getResponse()->getContent(), true);

Pour obtenir le contenu JSON d'une réponse. Nous allons tester que l'inscription et la connexion fonctionnent bien :

  • Envoyez une requête à /api/register, ajoutez des assertions qui vérifient que :
    • La réponse est un succès (code 200),
    • Le retour est un objet JSON contenant bien le champ id et email
  • Envoyez des requêtes à /api/login de manière à vérifier que:
    • L'identification avec un identifiant et/ou mot de passe incorrect retourne bien une erreur 401
    • L'identification avec les identifiants corrects fonctionne bien
  • Envoyez à nouveau une requête à /api/register avec les même identifiants, et vérifiez que la requête ne fonctionne pas (car l'e-mail est déjà présente)

Écrivez une méthode registerAndLogin qui inscrit un utilisateur, s'identifie, et retourne la réponse retournée par l'identification (qui devrait être le jeton).

Test des messages

Ajoutez maintenant une nouvelle classe de test MessagesApiTest.

Écrivez un test testMessagesSearch() qui recherche des messages autour d'une adresse qui ne devrait donner qu'un seul résultat. On vérifiera que le contenu du message est celui attendu.

Écrivez un test testMessagesSearchNoResult(), qui recherche des messages pour une adresse qui ne devrait donner aucun résultat (par exemple: 1 rue de la paix, Paris).

Écrivez une méthode testPostMessage() qui inscrit un utilisateur (vous pourrez faire hériter MessagesApiTest de UsersApiTest pour réutiliser registerAndLogin), puis qui publie un message.

Vous aurez besoin de transmettre le jeton dans les en-têtes HTTP à l'aide de l'en-tête:

Authorization: Bearer [token]

On vérifiera en contactant /api/messages que le message a bien été enregisté et peut être retrouvé.