Il existe plusieurs raisons de rédiger des tests automatisés, et cette tâche peut sembler relativement simple. Cependant, rédiger de « bons » tests automatisés est nettement plus difficile et nécessite une grande expérience ainsi qu’une formation ciblée.
Dans cet article, j’ai rassemblé quelques critères (généraux) à vérifier pour que les tests automatisés soient de bonne qualité. Ces critères sont définis à travers douze caractéristiques et, lorsqu’ils sont remplis, la définition de « bons » tests automatisés est atteinte.
Voici quelques objectifs généraux qui pourraient s’appliquer :
- Les tests doivent nous aider à améliorer la qualité.
- Les tests doivent nous aider à comprendre le système.
- Les tests doivent réduire (et non augmenter) les risques.
- Les tests doivent être faciles à exécuter.
- Les tests doivent être faciles à écrire et à maintenir.
- Les tests doivent nécessiter un minimum de maintenance à mesure que le système évolue autour d'eux.
Les tests doivent nous aider à améliorer la qualité
1. Le test comme spécification
Si vous utilisez le TDD (développement piloté par les tests) ou le BDD (développement piloté par le comportement, c'est-à-dire le développement « test-first »), les tests vous permettent de définir ce que le système fera avant même de commencer à le développer. En réfléchissant à différents scénarios afin de les transformer en tests, nous identifions plus facilement les domaines où les exigences sont ambiguës ou contradictoires. Une telle analyse clarifie l’objectif de la spécification, ce qui conduit à une conception plus précise et améliore la qualité du logiciel.
2. Un rempart contre les défauts
Les tests automatisés permettent de détecter les bogues, mais ce n’est pas là leur objectif principal. Les tests automatisés empêchent l’introduction de bogues. Considérez les tests automatisés comme un moyen de repousser les défauts, ce qui empêche les bogues de réapparaître dans notre logiciel une fois que nous nous sommes assurés qu’il ne contenait plus de bogues. Lorsque nous disposons de tests de régression efficaces et complets, il n’y a pas de bogues, car les tests signalent les défauts avant même que nous ne validerions notre code.
3. Identification des défauts
Si les tests automatisés sont relativement courts (c’est-à-dire que nous ne testons qu’un seul comportement dans chacun d’eux), nous serons en mesure de localiser rapidement l’erreur, en nous basant sur le test qui échoue. Mais pour y parvenir, nous devons écrire des tests pour tous les scénarios possibles afin de couvrir chaque unité du logiciel. Les tests ne doivent jamais contenir d’ambiguïtés. Il est donc essentiel de veiller à ce que les tests restent aussi simples et concis que possible (faible complexité, format cohérent et test d’un seul comportement par test).
Les tests doivent nous aider à comprendre le système
4. Les tests comme documentation
Les tests automatisés permettent de mettre clairement en évidence le fonctionnement attendu du code. Ils indiquent quel devrait être le résultat (c'est-à-dire le résultat attendu d'une ou plusieurs instructions).
Si nous voulons savoir comment le système effectue une opération, nous pouvons lancer le débogueur, exécuter le test et parcourir le code pas à pas pour voir comment il fonctionne. Les tests unitaires font office de documentation pour le système.
Les tests doivent réduire (et non augmenter) les risques
5. Les tests comme filet de sécurité
Modifier un code ancien est risqué, car on ne sait souvent pas ce qu’on risque de casser, et il est également difficile de savoir si on a cassé quelque chose ! Il faut travailler très lentement et avec précaution, et effectuer de nombreuses analyses manuelles avant d’apporter la moindre modification.
En revanche, lorsque nous travaillons sur du code disposant d’une suite de tests automatisés, nous pouvons avancer beaucoup plus rapidement. Les tests détecteront les effets secondaires inattendus des modifications et nous signaleront si nous avons causé une panne. De cette manière, les tests automatisés font office de filet de sécurité qui nous permet d’oser prendre des risques.
6. Aucun risque lié aux tests
Nous devons veiller à ne pas introduire de nouveaux types de problèmes dans le système à la suite des tests automatisés. Séparez le code de test du code de production afin d’éviter de créer des dépendances spécifiques aux tests dans le système (ce qui est particulièrement important pour le code des tests unitaires). Tout le code et toutes les bibliothèques spécifiques aux tests doivent être intégrés par le test, et uniquement dans la version de test et dans l’environnement de test. Les dépendances de test et le code de test ne doivent en aucun cas se retrouver dans le code final lorsqu’il est compilé pour la production.
Les tests doivent être faciles à exécuter
Quatre caractéristiques spécifiques facilitent l'exécution des tests automatisés. Grâce à ces quatre caractéristiques, il suffit de cliquer sur un bouton (ou, mieux encore, de déclencher automatiquement les tests) pour obtenir les précieuses informations fournies par les tests :
-
Les tests doivent être entièrement automatisés afin de pouvoir être exécutés sans effort.
- Les tests doivent être auto-évaluatifs afin de pouvoir détecter et signaler les erreurs sans inspection manuelle.
- Les tests doivent être reproductibles afin de pouvoir être exécutés plusieurs fois avec les mêmes résultats.
- Chaque test doit être indépendant afin de pouvoir s'exécuter de manière autonome.
7. Tests entièrement automatisés
Un test pouvant être exécuté sans aucune intervention manuelle est un test entièrement automatisé. Le respect de cette caractéristique est une condition préalable au respect des autres.
8. Auto-évaluation
Un test d’auto-évaluation peut intégrer tout ce dont il a besoin pour vérifier que le résultat attendu est correct. Le test ne nous alerte que lorsque le résultat n’est pas validé ; par conséquent, une exécution réussie du test ne nécessite aucun effort manuel.
9. Testsreproductibles
Un test reproductible peut être exécuté à l'infini tout en donnant exactement les mêmes résultats, sans aucune intervention ni analyse humaine entre les exécutions.
Les tests doivent être faciles à écrire et à maintenir
Lorsque nous modifions le comportement d’une partie d’un système, nous devons nous attendre à ce qu’un petit nombre de tests soient affectés par nos modifications. L’un des avantages de l’automatisation des tests est de faciliter les modifications. Nous devons donc toujours veiller à ce que nos tests ne produisent pas l’effet inverse (c’est-à-dire qu’ils ne rendent pas les modifications plus difficiles). Les tests doivent nécessiter un minimum de maintenance à mesure que le système évolue autour d’eux.
10. Des testssimples
Concentrez-vous sur les tests plutôt que sur la manière de les coder concrètement. Cela signifie que les tests doivent être simples/triviaux (faciles à lire, à écrire et à maintenir). Nous devons nous efforcer de vérifier une seule condition par test en créant une méthode de test distincte pour chaque combinaison unique de conditions. Chaque méthode de test doit tester le système en suivant un seul chemin au sein de celui-ci.
11. Tests expressifs
Une bibliothèque de méthodes d’aide permettant de construire un langage de test spécifique au domaine permet à la personne qui écrit le code de test d’exprimer les concepts qu’elle souhaite tester, sans avoir à traduire ses idées en un code beaucoup plus détaillé.
12. Décomposer les problèmes
Séparez le code de test du code de production (conservez la structure et la logique du code de production, mais dans une structure parallèle). Chaque test doit se concentrer sur un seul problème afin d’éviter des tests complexes et peu clairs.
Résumé
Il existe une différence entre un test et un « bon » test, mais il est souvent difficile de savoir comment définir ce qu’est un « bon » test. Dans cette liste de contrôle, j’ai présenté 12 caractéristiques de bonnes pratiques en matière d’automatisation des tests, qui permettent de rédiger facilement des tests et d’assurer une maintenance adéquate – deux facteurs essentiels pour un système.