Où placer chaque test dans votre pipeline CI/CD ?
Vous poussez du code et attendez. Cinq minutes passent. Dix minutes. Le pipeline tourne encore. Finalement, il échoue — mais l'erreur vient d'un test unitaire qui aurait dû s'exécuter dans les trente premières secondes. Vous venez de perdre dix minutes de votre temps et de ressources de calcul.
C'est la tension centrale dans la conception d'un pipeline : exécutez trop de tests tôt, et les développeurs attendent trop longtemps pour obtenir un retour. Exécutez trop peu de tests, et des défaillances critiques passent jusqu'à l'environnement de staging ou de production. La solution n'est pas de tout exécuter partout, mais de placer chaque type de test à l'étape où il apporte le plus de valeur pour le moindre coût.
Le principe : d'abord rapide et peu coûteux
La règle est simple : exécutez les tests rapides et peu coûteux en premier. Exécutez les tests lents et coûteux plus tard, et seulement après que les tests précédents ont réussi.
« Peu coûteux » signifie ici faible en temps de calcul, en configuration d'environnement et en préparation de données. Un test unitaire qui s'exécute en quelques millisecondes et ne nécessite pas de base de données est peu coûteux. Un test de bout en bout qui démarre un environnement complet, prépare des données et simule un parcours utilisateur est coûteux.
« Rapide » fait référence à la boucle de retour. Un développeur doit savoir en une minute ou deux si son changement a cassé quelque chose de fondamental. Attendre trente minutes pour découvrir une erreur de logique basique n'est pas acceptable.
Il ne s'agit pas de politique. Il s'agit de débit. Plus les développeurs obtiennent un retour rapidement, plus ils corrigent les problèmes vite. Plus un test est coûteux à exécuter, moins il doit être exécuté souvent.
Étape par étape : où placer les tests
Étape de commit : tests unitaires et tests de contrat
Le diagramme suivant résume le placement recommandé des tests à travers les étapes du pipeline :
Lorsqu'un développeur pousse du code, la première chose à exécuter est les tests unitaires. Ces tests sont rapides, ne nécessitent aucune dépendance externe et vérifient que les comportements individuels fonctionnent correctement. Un bon test unitaire prouve qu'un comportement significatif — du point de vue de l'appelant ou de l'utilisateur — produit le résultat attendu. Il ne se soucie pas des détails d'implémentation interne.
Certaines équipes exécutent également des tests de contrat à cette étape. Si le changement touche une interface ou un contrat d'API, le vérifier tôt évite les surprises en aval. Les tests de contrat sont généralement assez rapides pour être exécutés en même temps que les tests unitaires.
Ce qui ne doit pas être exécuté ici : les tests d'intégration, les tests de bout en bout, ou tout test nécessitant une base de données, un service externe ou un environnement complet. Ceux-ci viennent plus tard.
Étape de build : tests d'intégration et tests de contrat (à nouveau)
Après que le code a compilé et produit un artefact ou une image conteneur, les tests d'intégration entrent en jeu. À cette étape, l'application existe en tant qu'unité exécutable. Les tests d'intégration vérifient que l'application se connecte correctement à ses dépendances — bases de données, files d'attente de messages ou autres services.
Ces tests utilisent généralement des doubles de test ou des conteneurs légers, pas des environnements de staging complets. Ils vérifient que le câblage est correct : l'application peut ouvrir une connexion, envoyer une requête et gérer une réponse.
Les tests de contrat sont souvent exécutés à nouveau ici, contre l'artefact construit. Cela garantit que le code compilé satisfait toujours le contrat, pas seulement le code source.
Étape de staging : tests de bout en bout et tests de fumée
Le staging doit refléter la production aussi fidèlement que possible. C'est ici que vous exécutez les tests de bout en bout — mais uniquement pour les parcours utilisateur critiques. Pas toutes les pages, pas toutes les fonctionnalités. Seulement les flux qui comptent le plus : connexion, paiement, recherche, ou toute autre logique métier centrale.
Les tests de bout en bout sont lents et coûteux. Les exécuter pour chaque changement mineur est une perte de temps. Réservez-les pour les changements qui touchent des chemins critiques ou introduisent de nouvelles fonctionnalités.
Les tests de fumée sont également exécutés ici. Un test de fumée est une vérification rapide que l'application répond correctement après le déploiement. Si le test de fumée échoue en staging, ne passez pas en production. Arrêtez le pipeline et enquêtez.
Étape de production : tests de fumée et transactions synthétiques
En production, les tests doivent être minimaux et ne doivent pas affecter les utilisateurs. Exécutez un test de fumée immédiatement après le déploiement pour confirmer que les principaux points de terminaison répondent avec les codes de statut corrects. Ce n'est pas une validation approfondie — juste une vérification de bon sens que le déploiement n'a pas cassé l'application.
Les transactions synthétiques sont exécutées périodiquement, pas juste après chaque déploiement. Elles simulent des interactions utilisateur — comme se connecter ou effectuer un achat — pour détecter des régressions que le staging n'a pas attrapées. Comme elles sont exécutées selon un calendrier, elles attrapent des problèmes qui apparaissent avec le temps, comme des fuites mémoire ou des corruptions de données.
Ce qu'il ne faut pas faire
N'exécutez pas tous les tests à toutes les étapes. C'est l'erreur la plus courante. Exécuter des tests de bout en bout à l'étape de commit n'a aucun sens — l'environnement n'est pas prêt et le retour est trop lent. Exécuter à nouveau des tests unitaires à l'étape de production est un gaspillage — la logique n'a pas changé entre le staging et la production.
Une bonne règle empirique : si un test a réussi à une étape antérieure, ne le répétez pas à une étape ultérieure à moins que le changement d'environnement ne puisse affecter le résultat. Les tests unitaires ne dépendent pas de l'environnement, donc ils n'ont pas besoin d'être exécutés à nouveau. Les tests de fumée dépendent du déploiement, donc ils doivent être exécutés dans chaque nouvel environnement.
Tests basés sur le risque dans le pipeline
Le placement des tests dépend également du risque. Un changement dans le système de paiement ou la logique d'authentification justifie plus de couches de tests. Un changement de couleur de bouton ou une faute de frappe dans un libellé nécessite seulement des tests unitaires et un test de fumée.
C'est le test basé sur le risque appliqué au pipeline : plus le risque du changement est élevé, plus il doit passer par des couches de tests. Plus le risque est faible, plus il peut traverser le pipeline rapidement.
Certaines équipes implémentent cela en étiquetant les changements ou en utilisant des politiques de branche. Les chemins critiques nécessitent des tests de bout en bout en staging. Les chemins non critiques les sautent. Cela maintient le pipeline rapide pour les changements à faible risque tout en maintenant la sécurité pour ceux à haut risque.
Liste de contrôle pratique pour le placement des tests
- Les tests unitaires sont exécutés à l'étape de commit. Rapides, sans dépendances, retour immédiat.
- Les tests de contrat sont exécutés aux étapes de commit et de build. Vérifient les interfaces tôt et contre l'artefact.
- Les tests d'intégration sont exécutés à l'étape de build. Vérifient les connexions aux dépendances en utilisant des conteneurs ou des doubles de test.
- Les tests de bout en bout sont exécutés uniquement à l'étape de staging. Couvrent les parcours utilisateur critiques, pas toutes les fonctionnalités.
- Les tests de fumée sont exécutés aux étapes de staging et de production. Vérifications rapides de bon sens après chaque déploiement.
- Les transactions synthétiques sont exécutées périodiquement en production. Attrapent les régressions avec le temps.
- Ne répétez pas les tests entre les étapes à moins que le changement d'environnement ne soit pertinent.
- Ajustez les couches de tests en fonction du risque. Les changements à haut risque obtiennent plus de couverture.
L'essentiel à retenir
Un test bien placé vous donne un retour rapide quand vous en avez besoin et une validation approfondie quand vous pouvez vous le permettre. L'objectif n'est pas de tout tester partout. L'objectif est d'attraper la bonne défaillance au bon moment, afin que votre équipe puisse la corriger avant qu'elle n'atteigne la production.