Aller au contenu
Réussir mon BTS SIO

Tape une notion, une commande ou le nom d'une épreuve.

Par exemple

Chapitre 216 minIntermédiaire

Les types de tests et la pyramide des tests

Par Josselyn C., prof de BTS SIO. Mis à jour le .

À la fin de ce chapitre, tu sauras

  • distinguer test unitaire, d'intégration, de bout en bout et d'acceptation ;
  • classer un test : fonctionnel ou non, boîte noire ou boîte blanche ;
  • doser les tests avec la pyramide et éviter le cornet de glace ;
  • placer chaque niveau de test dans le cycle en V et en agile.

4 exercices corrigés2 schémas

On classe les tests selon trois questions : quelle taille de logiciel ils vérifient (une fonction, plusieurs composants, l'application entière), quoi ils vérifient (une fonctionnalité, la performance, la sécurité) et qui les écrit (le développeur, l'équipe, l'utilisateur). Les tests unitaires, d'intégration, de bout en bout, de non-régression et d'acceptation ne sont pas concurrents : chacun attrape des défauts que les autres laissent passer. La pyramide des tests dit dans quelles proportions les combiner.

Les niveaux de test : du plus petit au plus grand

NiveauCe qu'il vérifieQui l'écritExemple dans Prêt'Matos
Test unitaireUne unité de code isolée : une fonction, une méthode, une classeLe développeurverifierReservation refuse un prêt de 16 jours
Test d'intégrationPlusieurs composants qui travaillent ensemble : une route, ses middlewares, la baseLe développeur, l'équipePOST /api/reservations enregistre la réservation en base et renvoie 201
Test système (ou de bout en bout)L'application entière, déployée, du point de vue de l'utilisateurL'équipe, les testeursJulie se connecte, réserve VP-02, voit la confirmation à l'écran
Test d'acceptationLe logiciel répond-il au besoin ?Le client, les utilisateurs, avec l'équipeNadia déroule le cahier de recette et signe le procès-verbal

Le test unitaire

Un test unitaire vérifie le comportement d'une petite unité de code, isolée du reste : il ne touche ni la base de données, ni le réseau, ni le disque, ni l'horloge réelle. Il s'exécute en quelques millisecondes et, quand il échoue, il désigne une fonction précise. C'est le test que tu écriras le plus souvent ; les chapitres 3 à 6 lui sont consacrés.

js
test('refuse un prêt de 16 jours', () => {
  const demande = { materiel: 'VP-02', debut: '2027-03-15', fin: '2027-03-30' };
  expect(verifierReservation(demande, [], '2027-03-08').motif).toBe('Un prêt dure au plus 15 jours.');
});

Le test d'intégration

Un test d'intégration vérifie que des composants qui marchent séparément marchent aussi ensemble. Les défauts d'intégration sont nombreux et sournois : une route qui oublie le middleware d'authentification, une requête SQL qui renvoie les dates dans un autre format que celui attendu par le code, un nom de champ JSON différent entre l'API et le front. Chaque morceau a ses tests unitaires verts, et pourtant l'ensemble ne marche pas. Le chapitre 8 montre comment tester une API Express avec Supertest.

js
test('renvoie 409 quand le matériel est déjà réservé', async () => {
  const reponse = await request(app)
    .post('/api/reservations')
    .set('Authorization', 'Bearer jeton-julie')
    .send({ materiel: 'PC-07', debut: '2027-03-12', fin: '2027-03-18' });

  expect(reponse.status).toBe(409);
});

Le test de bout en bout

Un test de bout en bout (end-to-end, E2E) pilote l'application entière comme le ferait un utilisateur : un vrai navigateur ouvre la page, remplit le formulaire, clique sur le bouton et vérifie ce qui s'affiche. Il traverse toutes les couches : front React, API, base de données. C'est le test le plus réaliste, mais aussi le plus lent (plusieurs secondes), le plus fragile (un libellé de bouton change et il casse) et le plus difficile à diagnostiquer (quand il échoue, le défaut peut être n'importe où). Le chapitre 9 l'écrit avec Playwright.

Fonctionnel ou non fonctionnel

Les niveaux disent à quelle échelle on teste. Les types disent quoi :

TypeQuestion poséeExemples
Test fonctionnelLe logiciel fait-il ce qu'il doit faire ?Une réservation valide est enregistrée ; un chevauchement est refusé
Test de performanceEst-il assez rapide, sous la charge prévue ?La liste des matériels répond en moins de 300 ms avec 20 utilisateurs simultanés
Test de sécuritéRésiste-t-il aux usages malveillants ?Un salarié ne peut pas lire les réservations des autres en changeant l'identifiant dans l'URL
Test d'utilisabilitéEst-il facile à utiliser ?Un nouveau salarié réserve un portable sans aide en moins de deux minutes
Test d'accessibilitéEst-il utilisable par tous, y compris au clavier ou avec un lecteur d'écran ?Chaque champ du formulaire a une étiquette lue par le lecteur d'écran
Test de compatibilitéFonctionne-t-il sur les navigateurs et appareils prévus ?Firefox, Chrome, Safari, en largeur téléphone

Le mot « test fonctionnel » désigne aussi, dans beaucoup d'équipes, un test qui vérifie une fonctionnalité du point de vue de l'utilisateur, sans regarder le code : il se situe alors entre le test d'intégration et le test de bout en bout. Ne t'arrête pas aux étiquettes, qui varient d'une entreprise à l'autre : demande-toi ce que le test vérifie et à quelle échelle. Les tests de performance et de sécurité ont leur chapitre 13.

Le test de non-régression

Une régression est une fonctionnalité qui marchait et qui ne marche plus après une modification. Le test de non-régression consiste à rejouer, après chaque modification, les tests qui passaient avant, pour vérifier que rien n'a été cassé. Ce n'est pas un niveau de plus : ce sont tes tests unitaires, d'intégration et de bout en bout, relancés systématiquement. On ajoute aussi, après chaque bug corrigé, le test qui l'aurait détecté. Le chapitre 11 donne la méthode.

Le test d'acceptation et la recette

Le test d'acceptation vérifie que le logiciel répond au besoin exprimé, et pas seulement qu'il fonctionne. En France, on parle de recette : le client (la maîtrise d'ouvrage, MOA) ou le Product Owner déroule un cahier de recette, des cas de test tirés des exigences ou des critères d'acceptation des user stories, puis prononce la réception dans un procès-verbal. En anglais, on parle d'user acceptance testing (UAT). Deux variantes existent pour les logiciels diffusés largement : le test alpha, par des utilisateurs dans les locaux de l'éditeur, et le test bêta, par des utilisateurs réels chez eux, sur une version presque finie. Le chapitre 14 montre comment rédiger un plan de test et un cahier de recette.

Le test de fumée

Un test de fumée (smoke test) est une vérification très rapide, juste après un déploiement, que l'essentiel fonctionne : l'application démarre, la page d'accueil répond, la connexion à la base marche. L'expression vient de l'électronique : on allume l'appareil et on vérifie qu'il ne fume pas. S'il échoue, inutile de lancer les autres tests : on revient à la version précédente.

bash
# Test de fumée de la recette de Prêt'Matos : l'API répond-elle ?
curl --fail --silent https://recette.pretmatos.example/api/sante

Boîte noire et boîte blanche

ApprocheLe testeur connaît…Il choisit ses cas à partir de…Exemple
Boîte noireLes entrées, les sorties et les règles, pas le codeLa spécification, les critères d'acceptationTester les durées 15 et 16 jours parce que la règle dit « au plus 15 jours »
Boîte blancheLe code sourceLes chemins du code : chaque if, chaque boucleÉcrire un test pour chacun des quatre return de verifierReservation
Boîte griseUn peu des deuxLa spécification et la structure (la base, l'API)Tester l'API en connaissant le schéma de la base

Les deux approches se complètent : la boîte noire trouve les cas que le développeur n'a pas codés (une règle oubliée), la boîte blanche trouve les branches du code qu'aucun test n'exécute. La couverture de code (chapitre 12) mesure ce second point.

Test statique et test dynamique

Tous les tests vus jusqu'ici exécutent le code : ce sont des tests dynamiques. Les tests statiques examinent le code ou les documents sans les exécuter :

  • la revue de code, quand un collègue relit ta pull request (Git et GitHub) ;
  • l'analyse statique : un linter comme ESLint, le vérificateur de types de TypeScript ou du compilateur C#, un outil d'analyse de sécurité (SAST) ;
  • la relecture d'une spécification ou d'une user story, qui trouve les ambiguïtés avant même d'écrire le code.

Un test statique est souvent le moins cher de tous : ESLint signale une variable inutilisée ou un await oublié avant que tu lances quoi que ce soit.

La pyramide des tests

Combien écrire de tests de chaque niveau ? La pyramide des tests, popularisée par Mike Cohn dans les années 2000, répond par une image : une large base de tests unitaires, une couche plus fine de tests d'intégration, une pointe de tests de bout en bout.

Tests manuels : exploration et recetteBout en boutIntégrationUnitairesTrès peuplusieurs secondes chacunex. : Julie réserve VP-02Moins nombreux10 ms à 1 s chacunex. : la route de réservationNombreuxquelques millisecondesex. : verifierReservationEn montant : plus réaliste, mais plus lent, plus fragile, plus cher à maintenirEn descendant : plus rapide, plus stable, plus précis quand il échoue
La pyramide des tests : beaucoup de tests unitaires, moins de tests d'intégration, très peu de tests de bout en bout

Pourquoi cette forme ? Parce que les tests du bas sont rapides, stables et précis : mille tests unitaires tournent en une seconde, et celui qui échoue désigne la fonction fautive. Les tests du haut sont réalistes mais lents et fragiles : un test de bout en bout qui échoue peut venir du front, de l'API, de la base ou d'un réseau lent. On vérifie donc chaque règle métier en détail en bas, et on garde le haut pour quelques parcours essentiels, comme « réserver un matériel » et « enregistrer une sortie ».

Pour les applications front-end, Kent C. Dodds a proposé en 2018 une variante, le trophée des tests : une base d'analyse statique (ESLint, TypeScript), peu de tests unitaires, beaucoup de tests d'intégration de composants, et quelques tests de bout en bout. L'idée est la même : investir là où le rapport confiance / coût est le meilleur pour ton type d'application. Retiens la règle commune : chaque règle se teste au niveau le plus bas possible, et les niveaux du haut vérifient que les morceaux s'assemblent.

Les tests dans le cycle de vie du projet

Dans un projet mené en cycle en V (gestion de projet), chaque étape de conception, sur la branche descendante, a sa phase de test sur la branche montante. Les tests sont préparés au moment de la conception, même s'ils sont exécutés plus tard.

Expression des besoinsSpécifications fonctionnellesConception généraleConception détailléeCodageTests unitairesTests d'intégrationTests de validationRecettevérifie le besoinvérifie les spécificationsvérifie l'architecturevérifie la conception détailléeConception :du général au détailTests :du détail au généraltemps
Dans le cycle en V, chaque étape de conception a sa phase de test, préparée en même temps qu'elle

En agile (Scrum), il n'y a pas de grande phase de test à la fin : chaque user story est testée dans le sprint où elle est développée. La Definition of Done de l'équipe exige en général que les tests automatisés soient écrits et passent, et le Product Owner vérifie les critères d'acceptation de chaque story (user stories et critères d'acceptation). On parle de shift left : déplacer les tests vers la gauche du calendrier, le plus tôt possible.

Qui teste quoi ?

ActeurCe qu'il testeAvec quoi
Le développeurSon code, au fur et à mesureTests unitaires et d'intégration, sur son poste puis dans la CI
L'équipe de développement (MOE)L'application assembléeTests de bout en bout, tests de non-régression, tests de performance
Le relecteurLe code d'un collègueRevue de pull request
Le Product Owner ou la MOALa conformité au besoinCritères d'acceptation, cahier de recette
Les utilisateurs clésL'usage réelRecette, tests bêta
La sécurité ou un auditeur externeLa résistance aux attaquesRevue de code, SAST, DAST, test d'intrusion autorisé

Exercices

Exercice 1 sur 4 Quel niveau de test ? Réussi À revoir

Pour chaque test de Prêt'Matos, donne son niveau (unitaire, intégration, bout en bout, acceptation) et, s'il y a lieu, son type non fonctionnel.

  1. Vérifier que joursDeRetard('2027-03-14', '2027-03-17') renvoie 3.
  2. Vérifier que GET /api/reservations/mes sans jeton renvoie 401.
  3. Nadia réserve un portable sur le serveur de recette et confirme que l'écran correspond à ce qu'elle a demandé.
  4. Un robot ouvre Chrome, se connecte avec le compte de Julie, réserve VP-02 et vérifie le message affiché.
  5. Vérifier que l'API répond en moins de 300 ms à 20 utilisateurs simultanés.
  6. Vérifier que la requête du dépôt MySQL renvoie les dates au format AAAA-MM-JJ.
Voir la réponseMasquer la réponse de l'exercice 1
  1. Unitaire : une fonction pure, isolée.
  2. Intégration : la route et son middleware d'authentification ensemble. C'est aussi un test de sécurité (contrôle d'accès).
  3. Acceptation (recette) : l'utilisatrice valide la conformité au besoin.
  4. Bout en bout : toute l'application, pilotée par un navigateur.
  5. Test non fonctionnel de performance (test de charge), au niveau système.
  6. Intégration : le code et la vraie base de données ensemble. Un test unitaire avec un dépôt en mémoire ne verrait pas ce défaut.

Tu avais trouvé ?

Exercice 2 sur 4 Diagnostiquer une suite de tests Réussi À revoir

L'équipe d'un projet de gestion de stages a 4 tests unitaires, 6 tests d'intégration et 85 tests Selenium qui remplissent les formulaires dans un navigateur. La suite complète dure 52 minutes et, deux fois sur trois, un ou deux tests échouent sans que le code ait changé.

  1. Comment s'appelle cette forme de suite ?
  2. Pourquoi est-elle lente et instable ?
  3. Propose trois actions.
Voir la réponseMasquer la réponse de l'exercice 2
  1. Un cornet de glace : la pyramide à l'envers.
  2. Chaque test de bout en bout démarre un navigateur et traverse toutes les couches : il dure plusieurs secondes et dépend du temps de chargement, du réseau, de l'état de la base. Plus il y en a, plus la probabilité qu'au moins un échoue au hasard augmente.
  3. Par exemple : réécrire en tests unitaires les vérifications de règles métier (calculs, validations de dates) aujourd'hui faites par formulaire ; tester les routes de l'API avec des tests d'intégration ; ne garder que quelques tests de bout en bout pour les parcours essentiels (se connecter, déposer une convention, la valider) ; repérer et corriger chaque test instable au lieu de relancer la suite (les tests instables).

Tu avais trouvé ?

Exercice 3 sur 4 Boîte noire ou boîte blanche ? Réussi À revoir

  1. Une testeuse lit la règle « le rappel part la veille de la date de retour » et prépare un prêt qui se termine demain, un qui se termine aujourd'hui, un qui se termine après-demain. Quelle approche ?
  2. Un développeur lit le rapport de couverture, voit que le bloc catch de envoyerRappels n'est jamais exécuté et écrit un test où l'envoi échoue. Quelle approche ?
  3. Laquelle des deux aurait pu trouver une règle oubliée dans le code ?
Voir la réponseMasquer la réponse de l'exercice 3
  1. Boîte noire : les cas viennent de la règle, pas du code.
  2. Boîte blanche : le cas vient de la structure du code (une branche non couverte).
  3. La boîte noire : si le code ne contient pas la règle, aucune branche ne la représente, et la boîte blanche ne peut pas voir ce qui n'existe pas. C'est la limite principale de la couverture de code.

Tu avais trouvé ?

Exercice 4 sur 4 Placer les tests dans le cycle en V Réussi À revoir

Associe chaque document de conception de Prêt'Matos au niveau de test qu'il sert à préparer.

  1. Le cahier des charges, avec l'exigence « un salarié réserve lui-même le matériel ».
  2. La spécification de la route POST /api/reservations et de ses codes de retour.
  3. Le schéma d'architecture : front React, API Express, base MySQL.
  4. Le détail de l'algorithme de periodesSeChevauchent.
Voir la réponseMasquer la réponse de l'exercice 4
  1. Recette (tests d'acceptation) : on vérifiera avec la MOA que le besoin est couvert.
  2. Tests de validation (système, fonctionnels) : chaque code de retour spécifié devient un cas de test.
  3. Tests d'intégration : vérifier que le front parle bien à l'API, et l'API à la base.
  4. Tests unitaires : chaque cas de l'algorithme (chevauchement partiel, englobant, périodes contiguës) devient un test.

Tu avais trouvé ?

Chapitre terminé !

Fais les 4 exercices avant de passer à la suite : c'est en t'entraînant que tout se fixe.

chapitres
–
de série
–
du cours
–
Chapitre suivant : Écrire un bon test unitaire : AAA, nommage et cas à testerRevoir le sommaire du cours