Dans cet article, je voudrais partager mes idées sur la façon d'automatiser l'écriture de tests unitaires dans les applications react / redux. Ces idées sont nées dans l'une des discussions avec des collègues, en train de rédiger des tests, et, il me semble, la solution proposée a droit à la vie.
À propos du problème
Je voudrais omettre l'idée de la nécessité de tests unitaires et aller droit au but. Comment testons-nous les sélecteurs maintenant?
Le sélecteur redux est une fonction qui prend l'état de l'application (store) et renvoie le résultat. Même si un sélecteur est créé à l'aide de reselect createSelector () et combine plusieurs sélecteurs, il accepte également le stockage comme entrée.
Par conséquent, afin de tester le sélecteur, pour de bon, vous devez lui transférer le point final. Bien sûr, la création d'un magasin simulé peut éliminer les zones inutiles, mais si nous testons un sélecteur complexe qui combine d'autres sélecteurs de différentes parties du magasin, nous devrons recréer l'état complet ou presque complet. Et donc pour chaque cas.
Ici, vous pouvez aller de plusieurs façons:
- Pour recréer l'état de l'application dans un environnement de test et décharger l'état, en utilisant, par exemple, l'extension redux devtools;
- Créez simplement un objet, comme on dit, avec des stylos. Si l'application est volumineuse et que son état contient de nombreuses «branches», cela peut être un processus assez compliqué et minutieux.
Idée d'automatisation des processus
Imaginez que vous disposez d'un middleware qui, entre autres, connaît tous les sélecteurs de l'application. Un tel middleware peut, après chaque action, calculer tous les sélecteurs et préparer un cas de test composé de:
- Événement survenu (action);
- État de l'application (magasin);
- Le résultat de l'exécution de tous les sélecteurs avec cet état;
Ainsi, pour chaque action, nous aurons un ensemble de données: l'état de la demande de transmission aux sélecteurs et les résultats attendus - en fait, à comparer.
C'est-à -dire nous avons des ensembles de données d'une application réelle, dont la préparation a pris un minimum de temps.
Il ne reste plus qu'à apprendre à enregistrer ces données et à effectuer automatiquement des sélecteurs et à comparer le résultat, mais cette tâche est simple, technique et je l'ai résolue pour vous. Dans ce chapitre, je voulais juste faire passer l'idée.
Comment ça marche?
Si en général l'idée est claire (et elle vous semble adéquate :)), je vous propose de procéder à l'implémentation. Tout d'abord, nous avons besoin de l'extension de navigateur
Redux CheckState .
Cette extension obtient toutes les actions de votre application, exécute des sélecteurs et enregistre les cas de test. À la fin, vous cliquez sur le bouton et téléchargez le fichier avec les cas de test résultants.
Cela ressemble Ă ceci:

Pour que l'extension reçoive des données sur les actions en cours et puisse exécuter le silecteur, vous devez effectuer de petites manipulations avec le projet.
Étape 1. Exporter les sélecteurs
À la racine du projet, vous devez créer le fichier checkState.config.js et exporter tous les sélecteurs que vous souhaitez tester à partir de celui-ci. Dans mon projet de test, cela ressemble à ceci:
export { selectCategories, selectActiveCategory, selectIsCategoryActive, selectActiveCategoryId, } from "./state/category"; export { selectPopup, selectPopupType, selectIsPopupOpen, } from "./state/popup"; export { selectTasks, selectActiveTasks, selectActiveDoneTasks, selectActiveInProgressTasks, } from "./state/task";
Voir un exemple sur github .Étape 2. Implémentation du middleware
Vous devez maintenant ajouter un middleware, qui transférera toutes les actions et autres données vers l'extension.
Le code est extrĂŞmement simple:
import * as selectors from "./checkState.config"; const checkStateMiddleware = (options = {}) => { return window && window["__checkStoreExtension__"] ? window["__checkStoreExtension__"](options) : store => next => action => next(action); };
Dans mon application de test, vous pouvez également voir l'option d'implémentation dactylographiée.Ça y est, le codage à ce sujet est terminé. Maintenant, nous lançons l'application, ouvrons l'extension et commençons à utiliser l'application en tant qu'utilisateur. Vous devez terminer autant de jeux d'action que possible. Chaque action parfaite que vous verrez dans l'extension. Vous pouvez également cliquer sur n'importe quelle action et voir les résultats des sélecteurs.
Lorsque toute l'action est parfaite - il suffit de télécharger le fichier et de le mettre dans le projet. Maintenant, il ne reste plus qu'à exécuter les tests. C'est encore plus simple.
Exécution de tests
Pour exécuter les tests, j'ai préparé l'outil CLI. Installez le package:
npm i check-state -g
Après cela, dans le dossier du projet, exécutez la commande:
début de l'état de vérification
Vérifiez l'état CLI trouvera le fichier avec les cas de test générés par l'extension du navigateur, il trouvera et compilera les sélecteurs exportés (tandis que javascript et dactylographié sont pris en charge).
Après cela, tous les cas de test seront successivement passés, chaque sélecteur sera exécuté avec l'état d'application du cas de test et la valeur calculée sera comparée à celle attendue (également du cas de test). S'il n'y a pas de différence, nous verrons une ligne verte, s'il y a une ligne rouge, avec des informations qui aideront à diagnostiquer le problème:
- Le nom du sélecteur qui a renvoyé le mauvais résultat;
- Résultat attendu
- Résultat actuel;
- Un instantané de l'état de l'application à partir du scénario de test.
Un exemple de test «tombé».Afin que vous puissiez expérimenter l'outil, j'ai préparé une application de test qui a plusieurs sélecteurs et un état de vérification: l'
exemple d'application a déjà été implémenté
Conclusion
J'espère que vous avez aimé l'idée d'automatiser l'écriture des autotests, et peut-être que vous implémenterez cette approche dans votre projet :)
Si vous êtes intéressé par la mise en œuvre technique des outils:
Je serai ravi des idées et des commentaires :)