Chapitre 116 minIntermédiaire
C'est quoi un test logiciel ? Pourquoi tester son code
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- définir un test logiciel et distinguer erreur, défaut et défaillance ;
- expliquer pourquoi un bug coûte plus cher quand il est découvert tard ;
- citer les principes du test et choisir entre test manuel et automatisé ;
- écrire et lancer ton premier test automatisé avec Vitest.
4 exercices corrigés
Un test logiciel consiste à exécuter un programme, ou une partie de programme, dans une situation choisie, et à comparer le résultat obtenu au résultat attendu. S'ils diffèrent, le test a trouvé un défaut. On teste pour trouver les bugs avant les utilisateurs, et surtout pour pouvoir modifier le code sans peur de casser ce qui marchait. Ce chapitre pose le vocabulaire, les principes du test et ton premier test automatisé.
Le jour où Prêt'Matos a prêté deux fois le même portable
Prêt'Matos est en service depuis trois semaines. Karim, à la logistique, demande une petite évolution : « Quand quelqu'un rend un portable le matin, j'aimerais pouvoir le prêter à quelqu'un d'autre l'après-midi. » Yanis modifie la fonction qui détecte le chevauchement de deux périodes, change un <= en <, essaie une réservation à la main : elle passe. Il livre.
Le 14 mars au matin, Sofiane se présente au guichet pour emprunter PC-07, qu'il a réservé du 14 au 18 mars. Le portable n'est pas là : Julie, qui l'a réservé du 10 au 14, le rapportera en fin de journée, comme sa réservation l'y autorise. La modification a accepté deux prêts le même jour, sans savoir à quelle heure le premier emprunteur rendrait le matériel. Il faut appeler les deux salariés, chercher un autre portable, vérifier toutes les réservations enregistrées depuis la livraison et corriger celles qui se chevauchent. Une ligne de code, une demi-journée perdue, et la confiance des utilisateurs entamée.
Personne n'avait écrit de test pour le cas « une période commence le jour où l'autre finit ». S'il avait existé, il serait passé au rouge la seconde où Yanis a modifié la condition : le problème aurait été vu sur son poste, avant la livraison. C'est tout l'intérêt d'un test automatisé : il ne se fatigue pas, il n'oublie pas, et il rejoue en une seconde tous les cas que quelqu'un a pensé à écrire un jour.
Erreur, défaut, défaillance
Le vocabulaire du test distingue trois notions que le langage courant mélange sous le mot « bug ». Le glossaire de l'ISTQB, l'organisme international qui certifie les testeurs, les définit ainsi :
| Terme | Définition | Dans l'histoire de PC-07 |
|---|---|---|
| Erreur (error, mistake) | Une action humaine qui produit un résultat incorrect | Yanis change <= en < sans mesurer la conséquence |
| Défaut (defect, bug) | Une imperfection dans le code, la documentation ou la conception | La condition de chevauchement est fausse dans periodesSeChevauchent |
| Défaillance (failure) | Le système ne fait pas ce qu'on attend de lui, de façon visible | Deux salariés ont le même portable le même jour |
Une erreur produit un défaut ; un défaut ne provoque une défaillance que si on exécute le code fautif dans la bonne situation. Un défaut peut donc dormir des mois avant de se manifester. Le test cherche à provoquer les défaillances exprès, dans un environnement où elles ne coûtent rien.
Ce que coûte un bug selon le moment où on le trouve
Plus un défaut est découvert tard, plus il coûte cher : il faut le reproduire, comprendre le code écrit des semaines plus tôt, corriger, retester, redéployer, et réparer les dégâts qu'il a causés. Le même défaut de PC-07, à quatre moments différents :
| Découvert… | Par | Ce qu'il faut faire |
|---|---|---|
| En écrivant le code | Le test unitaire, sur le poste de Yanis | Relire la ligne, la corriger : une minute |
| Pendant la revue de code | Lina, qui relit la pull request | Un commentaire, un nouveau commit, une relecture : une heure |
| Pendant la recette | Nadia, qui déroule le cahier de recette | Une fiche d'anomalie, une correction, une nouvelle version en recette, un nouveau passage du cahier : une à deux journées |
| En production | Julie et Sofiane, au guichet | Gérer les utilisateurs, corriger les données, livrer un correctif en urgence, expliquer : des jours, et une perte de confiance |
Les sept principes du test
Ces principes, enseignés dans toutes les formations au test (ce sont ceux du programme de certification ISTQB), évitent les illusions les plus courantes.
| Principe | Ce qu'il veut dire | Pour Prêt'Matos |
|---|---|---|
| 1. Les tests montrent la présence de défauts, pas leur absence | Une suite de tests verte prouve que les cas testés marchent, pas qu'il n'y a plus de bug | 19 tests verts ne garantissent pas qu'aucune combinaison de dates ne pose problème |
| 2. Les tests exhaustifs sont impossibles | On ne peut pas essayer toutes les entrées : il faut choisir les cas | Rien que pour un matériel au planning vide, 365 dates de début × 15 durées possibles donnent 5 475 demandes ; avec les réservations existantes, c'est sans fin |
| 3. Tester tôt fait gagner du temps | Un défaut trouvé à l'écriture du code coûte moins qu'en production | Le test du chevauchement écrit avec la fonction |
| 4. Les défauts se regroupent | Quelques modules concentrent la plupart des défauts | Le calcul sur les dates concentre les bugs : c'est là qu'il faut le plus de tests |
| 5. Les tests s'usent | Rejouer toujours les mêmes tests ne trouve plus de nouveaux défauts : il faut en ajouter | Après chaque bug, un nouveau test (test de non-régression) |
| 6. Les tests dépendent du contexte | On ne teste pas une application de prêt comme un logiciel médical | Prêt'Matos privilégie les règles de réservation et les droits d'accès |
| 7. L'absence d'erreurs ne suffit pas | Un logiciel sans bug qui ne répond pas au besoin reste inutile | Si la logistique a besoin de prêter à la demi-journée, des tests verts ne la satisferont pas |
Le principe 2 est le plus important en pratique : puisqu'on ne peut pas tout tester, l'art du test consiste à choisir les cas qui ont le plus de chances de révéler un défaut. Le chapitre 3 te donne les techniques pour les trouver.
Tester à la main ou automatiser
Tu testes déjà ton code : tu lances l'application, tu remplis un formulaire, tu regardes si le résultat est bon. C'est un test manuel. Il a sa place, mais il a des limites.
| Test manuel | Test automatisé | |
|---|---|---|
| Qui l'exécute | Une personne qui suit des étapes | Un programme, lancé par une commande |
| Durée | Des minutes par cas | Des millisecondes à quelques secondes par cas |
| Fiabilité | La personne se lasse, saute une étape, juge à l'œil | Toujours les mêmes étapes, toujours la même vérification |
| Coût initial | Faible : on écrit une fiche | Plus élevé : on écrit du code |
| Coût de chaque nouvelle exécution | Le même à chaque fois | Presque nul |
| Idéal pour | L'ergonomie, l'exploration, la recette avec l'utilisateur | Les règles métier, les calculs, les droits d'accès, la non-régression |
Un test automatisé coûte plus cher à écrire la première fois, puis presque rien à rejouer. Dès qu'une vérification doit être refaite plus de deux ou trois fois, l'automatiser est rentable. Et elle doit être refaite après chaque modification du code : c'est ce qui rend l'automatisation indispensable.
Ton premier test automatisé
Voici la fonction qui calcule la durée d'un prêt dans Prêt'Matos. Les dates circulent au format AAAA-MM-JJ, celui des champs <input type="date"> et des colonnes DATE de MySQL.
// src/regles.js
const MS_PAR_JOUR = 24 * 60 * 60 * 1000;
// « 2027-03-12 » devient un numéro de jour : on compare des jours, pas des heures.
function numeroDeJour(dateIso) {
const [annee, mois, jour] = dateIso.split('-').map(Number);
return Date.UTC(annee, mois - 1, jour) / MS_PAR_JOUR;
}
// Du 12 au 18 mars : 7 jours, le premier et le dernier compris.
export function dureeEnJours(debut, fin) {
return numeroDeJour(fin) - numeroDeJour(debut) + 1;
}
Pour la tester, il te faut un framework de test : un outil qui trouve les fichiers de test, les exécute et affiche le bilan. En JavaScript, on utilise Vitest (le chapitre 4 le détaille). Dans un dossier de projet qui contient un package.json avec "type": "module" :
npm install --save-dev vitest
Puis on écrit un fichier de test à côté du code, avec le suffixe .test.js :
// src/regles.test.js
import { test, expect } from 'vitest';
import { dureeEnJours } from './regles.js';
test('compte le premier et le dernier jour', () => {
expect(dureeEnJours('2027-03-12', '2027-03-18')).toBe(7);
});
test('vaut 1 pour un prêt rendu le jour même', () => {
expect(dureeEnJours('2027-03-12', '2027-03-12')).toBe(1);
});
Chaque appel à test déclare un cas de test : un nom qui dit ce qui est vérifié, puis une fonction qui l'exécute. expect(valeur).toBe(attendu) est une assertion : si la valeur obtenue n'est pas exactement celle attendue, le test échoue. On lance tout avec npx vitest run :
✓ src/regles.test.js (2 tests) 2ms
Test Files 1 passed (1)
Tests 2 passed (2)
Les deux tests sont verts. Fais maintenant l'expérience qui convainc tout le monde : supprime le + 1 de dureeEnJours et relance.
FAIL src/regles.test.js > compte le premier et le dernier jour
AssertionError: expected 6 to be 7 // Object.is equality
- Expected
+ Received
- 7
+ 6
Le test est rouge : il te dit quel cas échoue, ce qu'il attendait (7) et ce qu'il a obtenu (6). Remets le + 1 : tout repasse au vert. Tu viens de vivre en dix secondes ce qui aurait évité la demi-journée perdue de PC-07.
Le vocabulaire du test
| Terme | Sens |
|---|---|
| Cas de test | Une situation précise à vérifier : des données d'entrée, une action, un résultat attendu |
| Jeu de données de test | Les données préparées pour les tests : réservations, salariés, matériels fictifs |
| Résultat attendu (oracle) | Ce que le programme devrait produire, connu avant d'exécuter le test |
| Assertion | L'instruction qui compare l'obtenu à l'attendu et fait échouer le test s'ils diffèrent |
| Suite de tests | L'ensemble des tests d'un projet, ou d'un fichier |
| Campagne de test | Une exécution planifiée d'un ensemble de tests, avec son bilan (souvent en recette) |
| Test vert, test rouge | Un test qui réussit, un test qui échoue |
| Faux positif | Un test rouge alors que le code est correct (le test lui-même est faux, ou dépend de l'heure) |
| Faux négatif | Un test vert alors que le code est faux (le test ne vérifie pas ce qu'il croit vérifier) |
| Test instable (flaky) | Un test qui passe ou échoue au hasard, sans que le code change |
Ce que le référentiel du BTS SIO attend
Les tests apparaissent dans les trois blocs de compétences, avec des intitulés que tu dois savoir citer :
| Bloc | Compétence | Ce que tu dois montrer |
|---|---|---|
| Bloc 1 (E5, les deux options) | Mettre à disposition des utilisateurs un service informatique : « réaliser les tests d'intégration et d'acceptation d'un service » | Des tests d'intégration et d'acceptation rédigés et effectués, et un rapport de test (compétences de l'E5) |
| Bloc 2 SLAM (E6) | Concevoir et développer une solution applicative : « réaliser les tests nécessaires à la validation ou à la mise en production d'éléments adaptés ou développés » ; « exploiter les fonctionnalités d'un environnement de développement et de tests » | Des tests unitaires, fonctionnels et d'intégration qui valident ce que tu livres |
| Bloc 2 SLAM (E6) | Assurer la maintenance corrective ou évolutive : « élaborer et réaliser les tests des éléments mis à jour » | Le test qui reproduit un bug corrigé, la suite de non-régression qui reste verte |
| Bloc 3 SLAM (E7) | Cybersécurité des services informatiques : les savoirs associés citent les tests de sécurité et l'audit de code | Lire ou écrire des tests unitaires qui prouvent un contrôle d'accès |
Le cours Épreuve E6 SLAM détaille ce que la commission vérifie pour chaque compétence.
Exercices
Exercice 1 sur 4 Erreur, défaut ou défaillance ? Réussi À revoir
Classe chaque situation.
- Une comptable reçoit un export CSV dont toutes les données sont dans la première colonne.
- Le développeur a écrit
split(',')alors que le fichier utilise le point-virgule. - Le développeur a lu trop vite la spécification et cru que le séparateur était la virgule.
- Une fonction contient une division par zéro quand une liste est vide, mais aucune liste vide n'a encore été traitée.
Voir la réponseMasquer la réponse de l'exercice 1
- Défaillance : le comportement visible n'est pas celui attendu.
- Défaut : l'imperfection est dans le code.
- Erreur : c'est l'action humaine à l'origine du défaut.
- Défaut sans défaillance pour l'instant : le code fautif n'a jamais été exécuté dans la situation qui le révèle. Un test avec une liste vide le ferait apparaître.
Tu avais trouvé ?
Exercice 2 sur 4 Calculer le résultat attendu Réussi À revoir
Sans exécuter le code, donne le résultat attendu de chaque appel, d'après la règle « premier et dernier jour compris ».
dureeEnJours('2027-03-01', '2027-03-15')dureeEnJours('2027-02-26', '2027-03-02')dureeEnJours('2028-02-26', '2028-03-02')dureeEnJours('2027-12-30', '2028-01-02')
Voir la réponseMasquer la réponse de l'exercice 2
- 15 : du 1er au 15, quinze jours.
- 5 : 26, 27, 28 février, puis 1er et 2 mars (2027 n'est pas bissextile).
- 6 : 2028 est bissextile, le 29 février s'ajoute.
- 4 : 30 et 31 décembre, 1er et 2 janvier.
Les cas 2 et 3 sont de bons tests : le passage de février est un endroit classique où un calcul de dates se trompe. Un test sur le cas 3 vérifie que la fonction connaît les années bissextiles ; ici, c'est Date.UTC qui s'en charge.
Tu avais trouvé ?
Exercice 3 sur 4 Un test qui ne prouve rien Réussi À revoir
Une élève teste sa fonction totalCommande ainsi :
test('calcule le total', () => {
const total = totalCommande([{ prix: 12.5, quantite: 2 }, { prix: 4, quantite: 3 }]);
console.log(total);
});
- Le test est vert. Que prouve-t-il ?
- Corrige-le.
Voir la réponseMasquer la réponse de l'exercice 3
- Presque rien : il prouve seulement que la fonction ne lève pas d'exception. Il n'y a aucune assertion, donc le test passe quel que soit le total calculé. Afficher une valeur n'est pas la vérifier : c'est un faux négatif garanti si le calcul est faux.
- On calcule l'attendu à la main : 12,5 × 2 + 4 × 3 = 25 + 12 = 37.
test('additionne prix × quantité de chaque ligne', () => {
const total = totalCommande([{ prix: 12.5, quantite: 2 }, { prix: 4, quantite: 3 }]);
expect(total).toBe(37);
});
Tu avais trouvé ?
Exercice 4 sur 4 Manuel ou automatisé ? Réussi À revoir
Pour chaque vérification de Prêt'Matos, dis si tu l'automatiserais ou si tu la ferais à la main, et pourquoi.
- Un prêt de 16 jours est refusé.
- Les libellés de l'écran de réservation sont compréhensibles par les salariés.
- Un salarié ne peut pas enregistrer la sortie d'un matériel (réservé à la logistique).
- L'application s'affiche correctement sur le téléphone de Karim.
- Le rappel de la veille part bien pour les prêts qui se terminent demain.
Voir la réponseMasquer la réponse de l'exercice 4
- Automatisé : une règle métier précise, à revérifier après chaque modification (test unitaire).
- Manuel : c'est un jugement humain, à faire en recette avec des utilisateurs.
- Automatisé : un contrôle d'accès doit être prouvé à chaque version (test d'intégration de l'API, chapitre 8). Une régression ici est une faille de sécurité.
- Manuel au moins une fois en recette ; on peut ensuite automatiser une partie avec Playwright en taille mobile (chapitre 9).
- Automatisé : la logique de sélection des prêts se teste avec une doublure de la messagerie (chapitre 7), sans envoyer de vrai courriel.
Tu avais trouvé ?