Suivre un principe TDD (Test-Driven Development) lors de l’écriture d’une application React Front-End peut sembler plus difficile que de faire de même sur le côté Back-end.
Premièrement, nous devons en quelque sorte rendre notre composant, simuler l’interaction de l’utilisateur avec un navigateur, répondre aux changements dans les accessoires et l’état, puis trouver un moyen de tester les méthodes asynchrones déclenchées par un clic sur un bouton par exemple.

Essayer de couvrir tous ces cas dans nos tests se traduit souvent par des tests difficiles à lire, ils dépendent souvent les uns des autres, nous simulons beaucoup et en retour, nous avons des tests complets d’anti-modèles.

Respectez Votre Temps

D’après ce que j’ai vu, de nombreux programmeurs créent d’abord des composants React fonctionnels, puis essaient de les couvrir avec des tests, juste pour réaliser que le composant ne peut pas être testé dans l’implémentation actuelle et qu’il doit être refactorisé. À cause de cela, ils perdent patience, temps et argent de leur employeur.

Solutions Disponibles

Heureusement pour nous, il existe de nombreuses bibliothèques de tests qui peuvent nous aider à résoudre ces problèmes. Nous pouvons essayer de rendre les composants React avec les réponses API Enzyme et Mock en utilisant MockAxios. Cependant, ces bibliothèques ont généralement tellement de méthodes et d’options qu’elles peuvent prêter à confusion, en particulier pour les personnes qui commencent à écrire des tests. Prenons Enzyme par exemple – quelle est la différence entre les méthodes Shallow, Mount et Render? Et que dois-je utiliser? Ce n’est pas ce que vous devriez être inquiet quand vous écrivez vos tests à mon avis. Cela devrait être aussi simple que possible.

Pour notre guide rapide, nous allons créer une petite application React dans laquelle après avoir cliqué sur un bouton, une blague aléatoire sur Chuck Norris sera récupérée et affichée.

Personne n’a jamais programmé en binôme avec Chuck Norris et a vécu pour en parler.

Commençons

Coup d’envoi en créant un projet React dans CodeSandbox puis en installant les dépendances suivantes (jest est déjà préinstallé si vous avez démarré depuis le lien ci-dessus):

  • axios — utilisé pour extraire des données de l’API externe
  • axios-mock-adapter—utilisé pour mocker les réponses du serveur
  • react-testing-library—bibliothèque de tests légère, facile à utiliser pour le rendu, simulant des actions et manipulant des async methods  (méthodes asynchrones)—créée parKent C. Dodds
  • jestpour exécuter les tests et créer des assertions

Structure des dossiers / fichiers

  • src / index.js—point d’entrée pour notre application React
  • src / jokeGenerator.js—notre composant conteneur, récupère, contrôle et fournit des données
  • src / joke.js—composant de présentation simple
  • src / __ tests __ / jokeGenerator.test.js—contient nos tests

Your first test

Chaque fois que nous créons un composant, nous allons d’abord écrire un test qui échoue, puis essayer de le faire passer. Commençons par écrire un test pour notre composant factice <Joke /> qui va afficher un texte à partir des accessoires.

jokeGenerator.test .js
jokeGenerator.test.js Image Source: Medium.com 

En lisant depuis le haut – nous utilisons une méthode de render de la part de reac-testing-library et nous passons le composant <Joke /> (qui n’existe pas encore à ce point). Il retourne un objet contenant peu de méthodes très utiles (liste complète des méthodes disponibles ici) par exemple getByTestId – retourne un élément HTML basé sur data-testid comme argument.

Ensuite, nous écrivons un expect utilisant la méthode ci-dessus et data-testid et vérifiez si l’élément contient le texte depuis les props et après avoir exécuté les tests, nous obtenons:

Joke is not defined

Oui, nous voulons que ça échoue! <Joke /> n’existe pas encore, nous avons créé un fichier joke.js vide jusqu’à présent. Nous avons écrit un test dans lequel nous pouvons clairement voir ce que nous attendons du composant à faire et maintenant notre travail consiste à faire passer le test sans modifier le code de test. Faisons-le alors:

joke.js
joke.js Image Source: Medium.com

Maintenant, si vous avez tout fait comme moi, le test devrait passer 🙂

Deuxième Composant

Notre deuxième composant sera chargé d’aller chercher une blague au hasard après avoir cliqué sur un bouton par l’utilisateur, en l’enregistrant dans l’état du composant et en le transmettant à notre composant <Joke />. Nous aimerions aussi afficher un message par défaut quand aucune blague n’a encore été chargée.Notre deuxième composant sera chargé d’aller chercher une blague au hasard après avoir cliqué sur un bouton par l’utilisateur, en l’enregistrant dans l’état du composant et en le transmettant à notre composant <Joke />. Nous aimerions aussi afficher un message par défaut quand aucune blague n’a encore été chargée.

Évidemment, nous commençons par le test en premier. C’est un composant plus important, donc nous allons écrire un test étape par étape et nous allons nous assurer qu’il passe aussi souvent que possible.

jokeGenerator.test.js
jokeGenerator.test.js Image Source: Medium.com

Nous sommes déjà familiers avec une méthode (de rendu mais cette fois nous prenons getByText de l’objet de retour. Comme vous auriez pu le deviner, la méthode renvoie un élément HTML s’il en existe un dans le DOM.

Exécutez les tests et …

JokeGenerator is not defined

Vous savez quoi faire avec:

jokeGenerator.js
jokeGenerator.js Image Source: Medium.com

Le test échoue toujours mais cette fois, il génère une erreur différente:

Unable to find an element with the text: You haven’t loaded any joke yet. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.

Corrigeons rapidement cela en introduisant un état (state) dans notre composant et en affichant un message par défaut quand il n’y a pas de joke dans state (l’état).

jokeGenerator.js
jokeGenerator.js Image Source: Medium.com

Les tests sont en cours et nous pouvons passer à ajouter de nouvelles fonctionnalités. Imaginez que l’on clique sur un bouton, le texte par défaut dans le composant disparaît pour laisser la place au message “Loading…” (Chargement). Cela semble assez simple, non? Nous pouvons tester ce scénario avec seulement trois lignes de code!
Importons d’abord la méthode Simulate, nous allons en avoir besoin:

import { render, Simulate } from “react-testing-library”
Append it to our second test -jokeGenerator.test.js
Append it to our second test -jokeGenerator.test.js (Image Source: Medium.com)

Différence entre queryByText et getByText est dans ce que les deux renvoient lorsque l’élément est introuvable. Le premier renvoie null et le second renvoie un message d’erreur. Réexécution des tests:

Unable to find an element with the text: Load a random joke…

Nous devons créer un bouton et définir la méthode onClick qui va mettre l’état de chargement à true.

jokeGenerator.js
jokeGenerator.js (Image Source: Medium.com)

Juste comme ça le test passe à nouveau. Maintenant, il est temps d’aller chercher notre blague au hasard! Eh bien … ce ne sera pas aléatoire dans nos tests. Nous allons juste utiliser MockAxios.

mport * as axios from "axios"
import MockAxios from “axios-mock-adapter”

Au-dessus de nos tests dans jokeGenerator.test.js insérez ces deux lignes de code:

Code to add above all— jokeGenerator.test.js
all tests — jokeGenerator.test.js (Image Source: Medium.com)

Première ligne crée une nouvelle instance de MockAxios avec un délai aléatoire et la deuxième ligne prend et exécute la fonction de rappel après avoir exécuté tous les tests dans ce fichier et supprime l’état mocked state de axios.

En haut de notre deuxième test où nous testons le composant <JokeGenerator /> ajoutez:

Top of the second test — jokeGenerator.test.js
Code to add at the Top of the second test — jokeGenerator.test.js (Image Source: Medium.com)

Il simule la réponse de tout appel GET effectué via axios. À la fin du même test:

jokeGenerator.test.js
jokeGenerator.test.js (Image Source: Medium.com)

N’oubliez pas d’importer ‘wait’

import { render, Simulate, wait } from “react-testing-library”

La méthode wait attend (4500 ms par défaut) jusqu’à ce qu’une fonction de rappel arrête de lancer une erreur. Il est vérifié à intervalles de 50 ms. Fondamentalement, nous attendons juste que le message de chargement disparaisse de DOM.

wait est également disponible en tant que package npm distinct (la reactive-testing-library l’utilise en tant que dépendance). Il a été créé par Łukasz Gozda Gandecki.

Après toutes les modifications de code et l’exécution des tests, nous devrions recevoir le message d’échec suivant:

Expected the element not to be present
Received : <div>Loading…</div>

Que pensez-vous que cela pourrait être? Selon notre test, nous nous attendons à ce que le message de chargement ne soit pas là. De plus, nous voulons extraire notre joke (blague) de l’API et l’enregistrer dans state (l’état) afin que la prochaine expect (attente) passe.

jokeGenerator.js
jokeGenerator.js (Image Source: Medium.com)
Insert into render() method — jokeGenerator.js
Insert into render() method — jokeGenerator.js (Image Source: Medium.com)

Les tests devraient passer à nouveau et nous sommes sûrs que tout fonctionne comme prévu, n’est-ce pas? Notez que nous n’avons jamais ouvert notre navigateur et vérifié manuellement si notre application fonctionne … Cependant, grâce à la façon dont nous écrivions nos tests (de sorte que nos tests ressemblent à la façon dont l’utilisateur utilise l’application), nous pouvons être sûrs à 100%  que L’application fonctionne simplement.

En tant que dernier morceau de code, ajoutons ceci à l’index.js et ouvrons le navigateur 🙂

index.js
index.js (Image Source: Medium.com)

Bonus

En raison de la façon dont nous avons écrit nos tests, nous pouvons les utiliser comme tests e2e sans ajouter une seule ligne de code!
Tout ce que nous devons faire est de supprimer toutes les lignes liées à MockAxios et recommencer les tests! Ils vont maintenant utiliser une véritable API externe. Cool, n’est-ce pas? 🙂

Note: Cet article est traduit, sa source en anglais est “Quick Guide to TDD in React” de son auteur Michał Baranowski

Tous les  codes sont disponible sur project’s CodeSandbox

J’espère que vous avez apprécié ce guide rapide sur TDD dans React et que vous avez appris quelque chose de nouveau aujourd’hui 🙂

LAISSER UN COMMENTAIRE

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.