
Développement Dirigé par les Tests dans Laravel
Lors de la création d'une application ou d'une nouvelle fonctionnalité, les tests peuvent être écrits en parallèle pendant son développement ou seulement à la toute fin. Dans le cas du TDD, c'est l'inverse. D'abord, nous écrivons un test pour une fonctionnalité inexistante, puis nous écrivons un code qui permettra à notre test de réussir.
Voici à quoi ressemble le cycle TDD en un coup d'œil :
- Nous écrivons un test pour une fonctionnalité inexistante.
- Nous exécutons le test, qui se termine bien sûr par une erreur. Sur la base de l'erreur générée, nous créons le code minimum qui permet de passer le test.
- Après avoir réussi le test, nous développons notre code et relançons les tests.
Nous pouvons aussi appeler ce cycle rouge, vert, refactorisation. Le premier test génère des erreurs (rouge), après avoir écrit le code responsable de la nouvelle fonctionnalité, le redémarrage du test se termine par un résultat positif (vert). Puis nous développons notre code (refactorisation).
Pour les besoins de cet article, supposons que nous allons développer une application avec la possibilité d'éditer et de supprimer des posts.
Préparation
Dans le cas de Laravel, beaucoup de choses ont déjà été préparées et la création d'un nouveau test est extrêmement facile. Pour commencer, nous devons commencer par la configuration de la base de données. Dans le fichier phpunit.xml, qui se trouve dans le répertoire principal du projet entre les balises, nous devons ajouter (ou dans le cas de Laravel 8 décommenter) le code suivant:
<server name="DB_CONNECTION" value="sqlite"/>
<server name="DB_DATABASE" value=":memory:"/>
Grâce à cela, lorsque nous lançons le test, nous n'avons pas à utiliser la base de données que nous utilisons tous les jours lors de la construction de l'application. Ensuite, nous devons créer le fichier approprié dans lequel nous allons écrire les tests. Comme toujours avec Laravel, l'artisan vient à la rescousse :
php artisan make:test PostTest
Créer une nouvelle ressource
Dans le fichier nouvellement créé tests/Feature/PostTest.php créez un nouveau test afin de configurer de nouvelles ressources.
/** @test */
public function un_post_peut_etre_crée()
{
$response = $this->post('/posts', [
'title' => 'Ceci est un post test.',
'body' => 'Du texte lorem ipsum.'
]);
$response->assertOk();
$this->assertCount(1, Post::all());
}
Notez quelques points clés :
- Un commentaire contenant @test. C'est nécessaire pour exécuter notre test.
- Le nom de la méthode est mieux s'il est long, mais il doit décrire correctement les activités réalisées dans le test, plutôt que court et dénué de sens.
Passons en revue ce que contient notre test. Après avoir envoyé une requête POST à / posts avec des données de titre et de corps, nous nous attendons à une réponse du serveur avec un statut de 200 et à ce qu'après le téléchargement de tous les posts de la base de données, ils soient égaux à un.
Malheureusement, lorsque nous relançons le test, le nombre de posts dans la base de données sera de 2 (post du test précédent et celui en cours). Nous devons donc vider la base de données à chaque fois que nous terminons le test. Notez que nous avons déjà importé le trait approprié en haut du fichier :
use Illuminate\Foundation\Testing\RefreshDatabase;
Nous devons juste l'utiliser dans notre classe :
use RefreshDatabase;
Essayons donc de lancer notre premier test, nous le faisons avec la commande :
./vendor/bin/phpunit --filter un_post_peut_etre_crée
Bien sûr, notre test échouera car nous n'avons pas de routage, de contrôleur ou de modèle prêt. Préparons donc toutes les choses nécessaires et essayons de relancer notre test, en créant le contrôleur, le modèle et le routage.
Gestion des erreurs
Parfois, une erreur sera renvoyée lors de l'exécution des tests. Son contenu ne sera pas très utile et à première vue, il sera difficile de comprendre quelle en est la cause :
1) Tests\Feature\PostTest::un_post_peut_etre_crée
Le code de statut de la réponse [500] ne correspond pas au code de statut attendu 200.
Pour obtenir des informations plus détaillées sur le bug, nous devons désactiver la gestion des erreurs de Laravel. Ajoutons donc ce code :
$this->withoutExceptionHandling();
Maintenant, après avoir redémarré le test, nous recevrons des informations qui nous seront beaucoup plus utiles :
1) Tests\Feature\PostTest::un_post_peut_etre_crée
Illuminate\Database\Eloquent\MassAssignmentException: Ajoutez [title] à la propriété remplissable pour autoriser l'affectation de masse sur [App\Models\Post]
Modification d'une ressource existante
Maintenant, créons un test pour vérifier la possibilité de modifier un post déjà créé. Nous ajoutons une nouvelle méthode :
/** @test */
public function un_post_peut_etre_modifié()
{
}
Lors de l'exécution de chaque test, nous commençons avec une base de données vierge qui ne contient aucune donnée. Le test doit donc commencer par la création d'une nouvelle ressource, puis essayer de la changer.
/** @test */
public function un_post_peut_etre_modifié()
{
$this->post('/posts', [
'title' => 'Titre du post',
'body' => 'Corps du post',
]);
$this->assertCount(1, Post::all());
$post = Post::first();
$this->patch('/posts/' . $post->id, [
'title' => 'Nouveau titre',
'body' => 'Nouveau corps',
]);
}
Nous devons vérifier que le titre et le contenu ont changé. Pour ce faire, nous avons juste besoin de télécharger le premier (et seul) post et de comparer son contenu :
$this->assertEquals('Nouveau titre', Post::first()->title);
$this->assertEquals('Nouveau corps', Post::first()->body);
Il est temps de lancer le test et de voir quel sera le résultat :
./vendor/bin/phpunit --filter un_post_peut_etre_modifié
Encore une fois, la réponse qui est renvoyée n'est pas très utile :
1) Tests\Feature\PostTest::un_post_peut_etre_modifié
Échec de l'assertion que deux chaînes sont égales.
--- Attendu
+++ Réel
@@ @@
-'Nouveau titre'
+'Titre du post’
Cependant, maintenant nous savons quoi faire dans ce cas. Alors désactivons la gestion des erreurs et relançons le test. Cette fois, nous devrions recevoir des informations sur l'absence de routage approprié. Selon la méthodologie TDD, nous devrions créer un routage et une méthode dans le contrôleur pour enregistrer les modifications du post. Si tout est fait correctement, le test devrait réussir.
Suppression d'une ressource
Nous commencerons le test de manière très similaire à la modification de la ressource. En raison du fait qu'il n'y a pas d'enregistrements dans notre base de données, nous devons commencer le test en ajoutant un nouveau post pour pouvoir tester sa suppression. Alors créons une nouvelle méthode.
/** @test */
public function un_post_peut_etre_supprimé()
{
$this->withoutExceptionHandling();
$this->post('/posts', [
'title' => 'Titre du post',
'body' => 'Corps du post',
]);
$this->assertCount(1, Post::all());
}
Ensuite, nous envoyons la requête appropriée et vérifions à nouveau si la table des posts ne contient pas d'enregistrements cette fois-ci.
$post = Post::first();
$this->delete('/posts/' . $post->id);
$this->assertCount(0, Post::all());
Bien sûr, le test échouera également cette fois-ci. C'est de cela qu'il s'agit avec le TDD. Il est maintenant temps de créer le routage approprié et une méthode dans le contrôleur qui gérera cette demande.
Regroupement de tests
Lorsqu'il y a plus de tests, il est utile de les regrouper. À l'avenir, vous n'aurez pas à les exécuter tous en même temps ou à démarrer chacun manuellement séparément. Pour ce faire, ajoutez @gorup
./vendor/bin/phpunit --group post_test_group
Résumé
Le TDD détecte les erreurs possibles dans l'application beaucoup plus rapidement que dans le mode normal de fonctionnement lorsque les tests sont écrits à la fin. Nous gagnons beaucoup de temps sur l'amélioration possible du code, et moins de personnes sont impliquées dans tout le processus. Cependant, il faut se rappeler que le TDD ne fonctionnera pas pour les petites applications, et nécessite des compétences supplémentaires de l'équipe de développement, qui sont gérées par le groupe QA.
Chez Droptica, nous avons de nombreuses années d'expérience dans la fourniture de services de développement PHP. N'hésitez pas à nous contacter si vous souhaitez en savoir plus sur le développement dirigé par les tests. Nos développeurs Laravel seront ravis de vous aider.
Et si vous êtes intéressé par Laravel, je vous encourage à lire mon article, dans lequel je discute du sujet de l'intuitivité et la rapidité d'écriture de code en utilisant Laravel.