Déterminez ce que vous devez tester et ce que vous pouvez exclure.
L'article précédent a abordé les principes de base des scénarios de test et ce qu'ils doivent contenir. Cet article aborde plus en détail la création de cas de test d'un point de vue technique, en détaillant ce qui doit être inclus dans chaque test et ce qu'il faut éviter. En substance, vous découvrirez la réponse aux questions éternelles "Que tester ?" ou "Que ne pas tester ?".
Consignes et tendances générales
Notez que des modèles et des points spécifiques sont cruciaux, que vous effectuiez des tests unitaires, d'intégration ou de bout en bout. Ces principes peuvent et doivent être appliqués aux deux types de tests. C'est donc un bon point de départ.
La simplicité avant tout
Lorsque vous rédigez des tests, l'un des points les plus importants à retenir est de faire simple. Il est important de prendre en compte la capacité du cerveau. Le code de production principal occupe une place importante, laissant peu de place à la complexité supplémentaire. C'est particulièrement vrai pour les tests.
Si vous avez moins de place disponible, vous pouvez être plus détendu dans vos efforts de test. C'est pourquoi il est essentiel de privilégier la simplicité dans les tests. En fait, les bonnes pratiques de test JavaScript de Yoni Goldberg soulignent l'importance de la règle d'or : votre test doit ressembler à un assistant et non à une formule mathématique complexe. En d'autres termes, vous devez pouvoir comprendre l'objectif de votre test en un coup d'œil.
Vous devez viser la simplicité dans tous les types de tests, quelle que soit leur complexité. En fait, plus un test est complexe, plus il est important de le simplifier. Pour y parvenir, vous pouvez opter pour une conception de test plate, où les tests sont aussi simples que possible et ne testent que ce qui est nécessaire. Cela signifie que chaque test ne doit contenir qu'un seul scénario de test, et que ce scénario doit être axé sur le test d'une seule fonctionnalité ou caractéristique spécifique.
Pensez-y de cette manière: il doit être facile d'identifier ce qui s'est mal passé lorsque vous lisez un test qui échoue. C'est pourquoi il est important de garder les tests simples et faciles à comprendre. Vous pourrez ainsi identifier et résoudre rapidement les problèmes lorsqu'ils surviennent.
Tester ce qui vaut la peine
La conception de test plate encourage également la concentration et permet de s'assurer que vos tests sont pertinents. N'oubliez pas que vous ne devez pas créer de tests uniquement pour la couverture. Ils doivent toujours avoir un but.
Ne pas tester les détails de l'implémentation
Un problème courant des tests est qu'ils sont souvent conçus pour tester les détails de l'implémentation, comme l'utilisation de sélecteurs dans les composants ou les tests de bout en bout. Les détails d'implémentation font référence à des éléments que les utilisateurs de votre code n'utilisent généralement pas, ne voient pas ou même ne connaissent pas. Cela peut entraîner deux problèmes majeurs dans les tests: les faux négatifs et les faux positifs.
Les faux négatifs se produisent lorsqu'un test échoue, même si le code testé est correct. Cela peut se produire lorsque les détails de l'implémentation changent en raison d'un refactoring du code de l'application. En revanche, les faux positifs se produisent lorsqu'un test est concluant, même si le code testé est incorrect.
Une solution à ce problème consiste à prendre en compte les différents types d'utilisateurs que vous avez. L'approche des utilisateurs finaux et des développeurs peut être différente, et leur interaction avec le code peut également l'être. Lorsque vous planifiez des tests, il est essentiel de tenir compte de ce que les utilisateurs verront ou avec quoi ils interagiront, et de faire dépendre les tests de ces éléments plutôt que des détails d'implémentation.
Par exemple, choisir des sélecteurs moins susceptibles de changer peut rendre les tests plus fiables: attributs de données au lieu de sélecteurs CSS. Pour en savoir plus, consultez Kent C. article de Dodds à ce sujet ou restez à l'affût : un article sur ce sujet sera publié ultérieurement.
Simulation: ne perdez pas le contrôle
La simulation est un concept vaste utilisé dans les tests unitaires et parfois dans les tests d'intégration. Il s'agit de créer des données ou des composants fictifs pour simuler des dépendances qui contrôlent complètement l'application. Cela permet d'effectuer des tests isolés.
L'utilisation de modèles dans vos tests peut améliorer la prévisibilité, la séparation des responsabilités et les performances. Si vous devez effectuer un test qui nécessite une intervention humaine (comme la validation d'un passeport), vous devrez le masquer à l'aide d'un modèle. Pour toutes ces raisons, les simulations sont un outil précieux à prendre en compte.
En même temps, la simulation peut affecter la précision du test, car il s'agit de simulations, et non de l'expérience utilisateur réelle. Vous devez donc faire preuve de prudence lorsque vous utilisez des maquettes et des bouchons.
Faut-il simuler dans les tests de bout en bout ?
En général, non. Toutefois, la simulation peut parfois vous sauver la vie. Ne l'excluons donc pas complètement.
Imaginez ce scénario: vous écrivez un test pour une fonctionnalité impliquant un service de fournisseur de services de paiement tiers. Vous vous trouvez dans un environnement de bac à sable qu'il a fourni, ce qui signifie qu'aucune transaction réelle n'a lieu. Malheureusement, le bac à sable ne fonctionne pas correctement, ce qui entraîne l'échec de vos tests. Le fournisseur de paiement doit résoudre le problème. Vous ne pouvez rien faire d'autre que d'attendre que le problème soit résolu par le fournisseur.
Dans ce cas, il peut être plus avantageux de réduire la dépendance envers les services que vous ne pouvez pas contrôler. Il est toujours conseillé d'utiliser la simulation avec précaution dans les tests d'intégration ou de bout en bout, car elle diminue le niveau de confiance de vos tests.
Spécificités des tests: bonnes pratiques et pratiques à éviter
En résumé, qu'est-ce qu'un test contient ? Y a-t-il des différences entre les types de tests ? Examinons de plus près certains aspects spécifiques adaptés aux principaux types de tests.
Qu'est-ce qu'un bon test unitaire ?
Un test unitaire idéal et efficace doit:
- Concentrez-vous sur des aspects spécifiques.
- Fonctionner de manière indépendante.
- Couvre les scénarios à petite échelle.
- Utilisez des noms descriptifs.
- Suivez le modèle AAA, le cas échéant.
- Garantir une couverture de test complète.
À faire ✅ | À éviter ❌ |
---|---|
Réduisez les tests au minimum. Testez une seule chose par scénario de test. | Écrivez des tests sur de grandes unités. |
Gardez toujours les tests isolés et simulez les éléments dont vous avez besoin en dehors de votre unité. | Incluez d'autres composants ou services. |
Gardez les tests indépendants. | S'appuyer sur des tests précédents ou partager des données de test. |
Couvrez différents scénarios et parcours. | Limitez-vous au scénario de réussite ou aux tests négatifs au maximum. |
Utilisez des titres de test descriptifs pour que vous puissiez immédiatement voir en quoi consiste votre test. | Test par nom de fonction uniquement, ce qui n'est pas assez descriptif: testBuildFoo() ou testGetId() . |
Essayez d'obtenir une bonne couverture du code ou une gamme plus large de cas de test, en particulier à ce stade. | Testez chaque classe jusqu'au niveau de la base de données (E/S). |
Qu'est-ce qu'un bon test d'intégration ?
Un test d'intégration idéal partage également certains critères avec les tests unitaires. Toutefois, vous devez prendre en compte quelques points supplémentaires. Un bon test d'intégration doit:
- Simulez les interactions entre les composants.
- Couvrez des scénarios réels et utilisez des maquettes ou des bouchons.
- Tenez compte des performances.
À faire ✅ | À éviter ❌ |
---|---|
Testez les points d'intégration: vérifiez que chaque unité fonctionne correctement lorsqu'elle est intégrée aux autres. | Testez chaque unité de manière isolée. C'est à cela que servent les tests unitaires. |
Tester des scénarios réels: utilisez des données de test dérivées de données réelles. | Utiliser des données de test générées automatiquement de manière répétitive ou d'autres données qui ne reflètent pas les cas d'utilisation réels |
Utilisez des maquettes et des bouchons pour les dépendances externes afin de garder le contrôle de votre test complet. | Créer des dépendances sur des services tiers, par exemple des requêtes réseau vers des services externes |
Utilisez une routine de nettoyage avant et après chaque test. | Oublier d'utiliser des mesures de nettoyage dans vos tests peut entraîner des échecs de test ou des faux positifs en raison d'une mauvaise isolation des tests. |
Qu'est-ce qu'un bon test de bout en bout ?
Un test de bout en bout complet doit:
- Reproduisez les interactions des utilisateurs.
- Couvre les scénarios essentiels.
- qui couvrent plusieurs couches ;
- Gérer les opérations asynchrones.
- Vérifiez les résultats.
- Tenez compte des performances.
À faire ✅ | À éviter ❌ |
---|---|
Utilisez des raccourcis basés sur des API. En savoir plus | Utilisez des interactions d'UI pour chaque étape, y compris le hook beforeEach . |
Utilisez une routine de nettoyage avant chaque test. Soyez encore plus attentif à l'isolation des tests que dans les tests unitaires et d'intégration, car le risque d'effets secondaires est plus élevé. | Oublier de nettoyer après chaque test Si vous ne nettoyez pas l'état, les données ou les effets secondaires restants, ils affecteront les autres tests exécutés ultérieurement. |
Considérez les tests de bout en bout comme des tests système. Vous devez donc tester l'ensemble de la pile d'application. | Testez chaque unité de manière isolée. C'est à cela que servent les tests unitaires. |
Utilisez un simulacre minimal ou aucun dans le test. Réfléchissez bien si vous souhaitez simuler des dépendances externes. | s'appuyer fortement sur les simulations. |
Tenez compte des performances et de la charge de travail, par exemple en évitant de tester trop de scénarios volumineux dans le même test. | Couvrir de grands workflows sans utiliser de raccourcis |