Plongeons-nous au cœur d’une opération chirurgicale complexe, où chaque geste compte et peut rapidement mettre en péril la vie du patient. Le chirurgien est maître à bord de cette délicate mission. Il s’appuie sur un équipement crucial : le moniteur de signes vitaux.
Ce dispositif surveille en temps réel la fréquence cardiaque, la pression artérielle, la saturation en oxygène, la température corporelle et la respiration du patient. A la moindre anomalie, il déclenche immédiatement une alerte sonore signalant aux médecins une détérioration des constantes vitales. Cette réactivité permet une intervention rapide et précise afin de stabiliser le patient et d’assurer le succès de l’opération.
Dans le monde du développement logiciel, garantir la qualité et la stabilité des applications est aussi crucial que veiller à la santé d’un patient en salle d’opération. Vous n’imaginez pas un chirurgien opérer sans un moniteur lui permettant de surveiller les constantes vitales de son patient ? De la même manière, un développeur travaillant sans tests unitaires navigue à l’aveugle et risque de compromettre la santé de son application à chaque nouvelle fonctionnalité ou correction de bug ! Les tests unitaires sont ainsi le stéthoscope du code, permettant de détecter les anomalies et de maintenir la robustesse du système.
![](https://www.soluxan.com/wp-content/uploads/2024/07/Monitor-operation-et-tests-1024x340.png)
Par ce parallèle, nous décryptons les 5 caractéristiques essentielles des tests unitaires et leurs équivalences dans les outils utilisés en chirurgie :
- Fast (Rapide)
- Isolated (Isolé)
- Repeatable (Répétable)
- Self-Validating (Auto-Validant)
- Timely (Opportun)
1. Fast : Le feedback instantané
En salle d’opération, imaginez un moniteur qui alerte une anomalie de nombreuses minutes après qu’elle ait eu lieu… Il sera peut-être trop tard ! Le chirurgien dépend d’un feedback immédiat pour pouvoir réagir en temps réel et sauver la vie de son patient.
Il en est de même pour les tests unitaires qui doivent fournir un retour rapide et constant. En effet, seul un feedback instantané permet de détecter et corriger les erreurs dans l’immédiat. Et lorsque l’on ajoute de nouvelles fonctionnalités dans un code, chaque seconde compte pour en assurer la stabilité. Ces tests doivent donc être très rapides, de l’ordre de la seconde, afin que le développeur puisse les lancer aussi fréquemment que nécessaire.
2 – Isolated : L’assurance de ne pas être sous influence
Retour en salle d’opération : que se passerait-il si les constantes vitales affichées sur le moniteur appartenaient au patient opéré dans la chambre voisine ? Une situation chaotique et dangereuse ! Le chirurgien a besoin d’un moniteur fiable qui lui donne des constantes dédiées pour un seul et unique patient, même s’il partage la même source d’énergie que d’autres moniteurs.
Les tests unitaires doivent eux-aussi être isolés. Chaque test doit produire un résultat indépendant des autres, évitant toute interférence qui pourrait fausser les conclusions. Cette indépendance permet entre autres de localiser et de corriger les erreurs sans ambiguïté.
3 – Repeatable : Avoir le même résultat quel que soit l’environnement
Il est impensable pour un chirurgien que son moniteur affiche des constantes vitales différentes pour le même patient selon s’il se trouve au bloc A du rez-de-chaussée ou au bloc B situé à l’étage de l’hôpital. Sinon, comment s’y référer ? Il doit pouvoir se fier à des mesures cohérentes et fiables peu importe l’environnement.
Ce principe s’applique également pour les tests unitaires. Ils doivent être répétables et déterministes, en produisant des résultats cohérents indépendamment de l’environnement dans lequel ils sont exécutés. Concrètement : un test qui réussit sur un poste de développement doit également réussir sur la plateforme d’intégration continue ou dans un environnement de test. Cette fiabilité garantit que le code fonctionne correctement en tout temps et en tout lieu, réduisant ainsi les mauvaises surprises en production.
4 – Self-Validating : L’art du diagnostic automatique
Et si après chaque geste, le chirurgien devait appuyer sur plusieurs boutons pour obtenir les constantes vitales de son patient ? Une telle complexité ralentirait l’opération et augmenterait les risques. Une fois configuré, son moniteur doit alors lui remonter automatiquement les constantes vitales comme la fréquence cardiaque et la pression artérielle, sans aucune intervention manuelle.
De la même manière les tests unitaires doivent être auto-validants. Il n’est pas possible pour développeur de comparer manuellement les données en sortie à chaque exécution pour décider si la fonctionnalité testée est correcte ou non. Les assertions intégrées aux tests doivent donc automatiquement valider les résultats. Ainsi en un simple coup d’œil à l’IDE (logiciel utilisé pour écrire les lignes de code), la saisie rouge ou verte permet de savoir si le code est conforme. Cela simplifie le processus et garantit une évaluation rapide et fiable de l’intégrité de l’application !
5 – Timely : Le bon timing
Il serait impensable que notre chirurgien attende d’avoir terminé son opération pour mettre en route le moniteur et savoir si le patient est toujours en vie. Le moniteur est donc branché avant toute intervention pour vérifier la stabilité des constantes du patient, puis il sert de guide à l’équipe médicale tout au long de l’opération. Pour cela, les sons émis par le moniteur agissent comme un GPS indiquant que tout se passe bien ou signalant qu’il faut intervenir.
De la même manière, les tests unitaires doivent être écrits et lancés au bon moment. C’est-à-dire le plus tôt possible, idéalement avant même que le code à tester ne soit écrit. Cette approche permet de détecter les erreurs dès le début du développement de nouvelles fonctionnalités et d’avoir ainsi des corrections plus simples et moins coûteuses. Une intervention rapide et préventive grâce aux tests unitaires assure la bonne santé et la robustesse de votre application dès les premières lignes de code.
Cette analogie avec l’intervention chirurgicale met en évidence la nécessité d’établir des tests unitaires au démarrage de tout projet de développement. Il ne s’agit pas de détails nice to have, mais bien de must have pour maintenir en bonne santé une application tout au long de son existence !
Vous pouvez retrouvez les cinq caractéristiques d’un bon test (F.I.R.S.T) dans le livre Clean Code de Robert C. Martin (page 132). Nous vous invitons également à étudier d’autres caractéristiques d’un bon test dans cet article rédigé par Kent Beck.
Autres types de tests
Bien qu’essentiels, les tests unitaires ne sont pas suffisants pour garantir la qualité du logiciel. Il en existe d’autres types tels que les tests d’intégration, qui vérifient que différentes parties du système fonctionnent correctement ensemble. Ces tests ont des temps de réponse plus longs, similaires aux examens pré- ou post-opératoires dans notre exemple (des analyses de sang, radios, IRM…) mais sont tout aussi indispensables pour assurer la stabilité et la cohérence du système.
Nous vous laissons désormais à vos blocs opératoires en espérant que cet article vous aidera à garder vos « patients » en bonne santé. 😉
Happy testing !
Rédigé par Aboudou, avec des remerciements à Younes et Tanguy qui ont pris du temps pour relire l’article avant sa publication afin que son contenu soit en accord avec l’intention qu’il souhaitait distiller.