12k
All articles

Les tests de fumée et pourquoi les agents n'arrêtent pas d'en écrire

Les smoke tests expliqués: quoi vérifier, où les exécuter, quoi exclure, et pourquoi les agents les ajoutent sans cesse à CI et aux déploiements.

OpenReplay Team
OpenReplay Team
Les tests de fumée et pourquoi les agents n'arrêtent pas d'en écrire

Un test de fumée (smoke test) est un petit ensemble de vérifications attestant qu’un système déployé est fondamentalement vivant : le processus a démarré, la page principale renvoie un 200, un utilisateur peut se connecter et la base de données répond à une requête. Il ne juge pas si le logiciel est correct ; il décide si exécuter le reste de la suite de tests vaut le temps investi.

Si vous livrez en CI depuis des années sans avoir jamais eu besoin de cette définition, vous n’êtes pas seul. L’expression arrive généralement sans préambule, et ces derniers temps elle arrive au sein d’une pull request : un smoke.sh ou un smoke.spec.ts qu’un agent de codage a ajouté en terminant autre chose.

Cet article traite de ce qui a sa place dans un test de fumée, de l’endroit où il s’exécute, de ce à quoi ressemble un test minimal en code, du filtre permettant d’en écarter le superflu, et des raisons pour lesquelles les agents en produisent avec une telle régularité.

Points clés à retenir

  • Un test de fumée vérifie qu’un système déployé est vivant (démarrage, 200 sur la page principale, connexion, une vraie lecture en base de données) et prend quelques secondes, pas quelques minutes.
  • Il s’exécute deux fois : comme première barrière dans la CI, et immédiatement après un déploiement, contre l’environnement réellement ciblé ; une exécution sur localhost ne peut pas détecter les défaillances de déploiement.
  • Une vérification n’a sa place dans la suite de fumée que si son échec bloque tous les utilisateurs, que tous les utilisateurs y passent, et qu’elle peut casser pendant le déploiement. Si les trois conditions ne sont pas réunies, elle va en régression.
  • Les agents de codage écrivent des tests de fumée parce qu’une tâche terminée exige un signal bon marché, binaire et rapide indiquant que rien de fondamental n’est cassé — ce qui est précisément ce que produit un test de fumée.
  • Fixez un plafond strict à la suite et déplacez tout ce qui le dépasse vers la régression ; une suite de fumée de douze minutes est une suite de régression mal nommée.

Qu’est-ce qu’un test de fumée ?

Un test de fumée répond à une seule question — « ce build est-il assez vivant pour être testé plus avant ? » — et son nom est couramment rattaché à la mise sous tension d’un matériel neuf en guettant la fumée. En logiciel, la forme est la même : un passage rapide et superficiel sur les chemins dont dépendent tous les utilisateurs, avec un résultat binaire et aucun avis sur la justesse du code.

Il se situe en dehors de la pyramide de tests habituelle plutôt que sur l’une de ses couches ; les couches elles-mêmes sont traitées dans Integration Tests vs End-to-End Tests et Unit vs Integration Testing in JavaScript: What to Use When. Un test de fumée est une barrière placée devant ces suites, pas un de leurs membres.

Où s’exécute un test de fumée ?

Les tests de fumée s’exécutent à deux endroits : comme première barrière dans la CI, avant le démarrage des suites plus longues, et immédiatement après un déploiement, contre l’environnement réellement ciblé. Le second emplacement est celui qui justifie son existence, et c’est aussi celui qu’on oublie le plus souvent.

Exécuter un test de fumée contre localhost en annule l’intérêt, car les défaillances qu’il est censé détecter ne surviennent qu’au déploiement : une variable d’environnement manquante, une migration jamais exécutée, un bundle d’assets jamais livré. Un processus démarré sur le runner de CI avec APP_URL=localhost et une base de données en mémoire toute fraîche ne dispose d’aucun de ces modes de défaillance. Ce type d’exécution est une vérification de démarrage (boot check), et les vérifications de démarrage sont utiles, mais c’est une chose différente et plus faible. Une exécution locale contre des services simulés ne peut échouer pour aucune des raisons qui font échouer un déploiement : elle ne devrait donc pas en porter le nom.

L’exécution post-déploiement est aussi le déclencheur naturel du rollback : AWS CodeDeploy exécute votre fonction de validation une fois que la nouvelle version sert du trafic de test, et un résultat en échec déclenche un rollback. Gardez toutefois à l’esprit la limite de ce signal. Un test de fumée post-déploiement au vert prouve que le système a répondu, pas que le parcours utilisateur fonctionne ; visionner les session replays des premières sessions réelles après une mise en production est la technique qui sépare les deux, car un bouton de paiement qui lève une erreur à cause d’un hash de chunk modifié n’apparaîtra jamais dans un code de statut.

À quoi ressemble un test de fumée ?

Une suite de fumée complète peut tenir en un court script qui frappe la cible réellement déployée sans aucun mock : une attente bornée sur l’endpoint de santé, une requête authentifiée, et une lecture qui traverse l’application jusqu’à la base de données.

#!/usr/bin/env bash
# smoke.sh: runs against the deployed target in $APP_URL, never localhost
set -euo pipefail

: "${APP_URL:?set APP_URL to the deployed base URL}"
: "${SMOKE_USER:?}" "${SMOKE_PASS:?}"

status() { curl --silent --output /dev/null --write-out '%{http_code}' "$@"; }

# 1. Wait for the process to come up. This absorbs container start-up, nothing else.
for _ in $(seq 1 "${SMOKE_RETRIES:-10}"); do
  [ "$(status "$APP_URL/health")" = "200" ] && break
  sleep 3
done
[ "$(status "$APP_URL/health")" = "200" ] || { echo "health: not 200"; exit 1; }

# 2. Login. Assert the one status your app returns (200 for a JSON API, 302 for a form post).
code=$(status --data-urlencode "email=$SMOKE_USER" \
              --data-urlencode "password=$SMOKE_PASS" "$APP_URL/login")
[ "$code" = "200" ] || { echo "login: got $code, expected 200"; exit 1; }

# 3. A real read through the app, with the credentials the app was deployed with.
body=$(curl --silent --fail "$APP_URL/api/products?limit=1") || { echo "query: request failed"; exit 1; }
[ -n "$body" ] || { echo "query: empty body"; exit 1; }

echo "smoke: ok"

La fonction utilitaire status s’appuie sur l’option --write-out '%{http_code}' de curl pour capturer le code de réponse, tandis que --output /dev/null jette le corps de la réponse. set -euo pipefail force le script à sortir dès le premier échec. La boucle de nouvelles tentatives n’existe que pour absorber le temps de démarrage après un déploiement ; ce n’est pas un moyen de masquer une vérification instable.

Chaque assertion nomme un statut exact. Chaque code de la RFC 9110 porte un sens : une vérification qui accepte « n’importe quelle réponse » n’est pas une vérification. Un 404 sur une route censée exister est une défaillance de déploiement, et un 302 n’est acceptable que là où le contrat prévoit une redirection. La troisième vérification compte plus qu’il n’y paraît. Pinguer le serveur de base de données avec un outil comme pg_isready confirme que le serveur accepte les connexions ; une lecture à travers l’application confirme que l’application peut atteindre la base de données avec la chaîne de connexion, les identifiants et le schéma avec lesquels elle a été déployée — précisément la classe de défaillances pour laquelle les tests de fumée existent.

Ce qui n’a pas sa place dans un test de fumée

Les cas limites, la logique métier, tout ce qui est lent et tout ce qui est instable n’ont pas leur place dans un test de fumée. Une vérification n’appartient à la suite de fumée que si les trois conditions suivantes sont réunies : son échec empêche tout utilisateur de faire quoi que ce soit, tous les utilisateurs y passent, et elle peut casser pendant un déploiement. Une vérification qui en satisfait moins de trois relève de la suite de régression. Cette formulation en trois questions apparaît dans les recommandations d’au moins un éditeur d’outils de test en CI ; il s’agit d’une heuristique, pas d’un standard.

Vérification candidateBloque tous les utilisateurs ?Tous les utilisateurs y passent ?Peut casser au déploiement ?Verdict
L’endpoint de santé renvoie 200OuiOuiOuiFumée
Connexion avec un compte de testOuiOuiOuiFumée
Un code promo applique une remiseNonNonOuiRégression
L’export CSV admin se téléchargeNonNonOuiRégression
L’e-mail de réinitialisation de mot de passe arriveNonNonOuiRégression

L’instabilité (flakiness) est à elle seule un motif de disqualification. Une vérification de fumée qui échoue aléatoirement apprend à l’équipe à relancer les barrières rouges, et une barrière que les gens relancent jusqu’à ce qu’elle passe n’est plus une barrière.

Pourquoi les agents de codage écrivent-ils sans cesse des tests de fumée ?

Les agents de codage écrivent des tests de fumée parce qu’un agent qui termine une tâche a besoin d’un signal bon marché, rapide et non ambigu lui indiquant qu’il n’a pas cassé tout le système — et c’est exactement le signal que produit un test de fumée. Un agent qui vient de modifier du code ne peut pas se permettre la suite complète à chaque itération et ne peut pas juger la justesse par simple inspection : il se tourne donc vers la vérification qui répond en quelques secondes à « est-ce que c’est toujours vivant ? » et renvoie un code de sortie propre.

Ce n’est pas un hasard. La documentation de Claude Code d’Anthropic recommande aux développeurs de fournir à l’agent quelque chose qu’il peut exécuter pour vérifier son propre travail, qu’il s’agisse d’une suite de tests, d’un build, d’un linter ou d’un petit script. Doté d’un signal qu’il peut lire lui-même, l’agent continue de travailler et de revérifier sans attendre qu’un humain repère l’erreur. Un script de fumée correspond parfaitement à cette description, ce qui explique pourquoi les dépôts écrits par des agents finissent souvent par en contenir un, même lorsque l’équipe n’a jamais employé le terme. C’est la raison pour laquelle les développeurs découvrent aujourd’hui le « test de fumée », souvent en en trouvant un dans un diff qu’ils n’ont pas écrit.

Lorsqu’un tel test apparaît dans une PR, examinez-le à l’aune de quatre questions. Lit-il l’URL cible depuis une variable d’environnement plutôt que de coder localhost en dur ? Assertionne-t-il un statut précis plutôt qu’un simple « pas une erreur » ? Se termine-t-il en quelques secondes ? Chaque vérification passe-t-elle le filtre des trois questions ci-dessus ? Un test de fumée écrit par un agent qui échoue à l’une de ces questions est soit une vérification de démarrage, soit un test de régression portant la mauvaise étiquette.

Le mode de défaillance : la suite grossit

Une suite de fumée cesse d’être une barrière dès l’instant où elle dépasse quelques secondes. Le schéma est prévisible : chaque fonctionnalité ajoute une vérification « au cas où », un agent en ajoute une autre après chaque tâche, et un beau jour la barrière prend douze minutes et les gens commencent à la contourner. À ce stade, c’est une suite de régression lente affublée du mauvais nom.

La solution est un plafond strict, avec déplacement vers la régression de tout ce qui le dépasse. Notre valeur par défaut recommandée est une poignée de vérifications, de l’ordre de cinq, qui se terminent en quelques secondes ; TestingXperts fixe la limite supérieure à dix minutes, au-delà desquelles les équipes commencent à sauter la barrière. Le chiffre exact importe moins que le fait d’en avoir un, écrit noir sur blanc et appliqué en revue — y compris lors de la revue des ajouts produits par des agents.

Conclusion

Un test de fumée est la plus petite preuve possible qu’un déploiement est vivant : santé, connexion, une vraie lecture, exécuté contre l’environnement que vous avez réellement livré, terminé en quelques secondes. Tout le reste relève de la régression. La prochaine fois qu’un agent vous tend un smoke.sh, vérifiez qu’il cible une URL réelle, qu’il assertionne des statuts exacts et qu’il reste sous le plafond, puis branchez-le pour qu’il s’exécute après chaque déploiement.

FAQ

Quelle est la différence entre un test de fumée et un health check ?

Un health check est un endpoint unique qu'un orchestrateur ou un load balancer interroge pour décider s'il faut router du trafic ou redémarrer un conteneur ; Kubernetes les appelle liveness probes et readiness probes. Un test de fumée s'exécute une fois par déploiement, appelle cet endpoint en plus d'une connexion et d'une lecture en base de données, et renvoie un code de sortie qui conditionne le pipeline. L'endpoint de santé est la première assertion du test de fumée, pas son substitut.

Quelle est la différence entre le smoke testing et le sanity testing ?

Le smoke testing est large et superficiel : il vérifie que les chemins essentiels d'un build sont vivants avant que des tests plus poussés ne commencent. Le sanity testing, dans la terminologie QA classique, est étroit et profond : il vérifie qu'un correctif ou un changement précis fonctionne sur un build ayant déjà passé le test de fumée, et il est souvent considéré comme un sous-ensemble des tests de régression. Dans un pipeline CI, la suite de fumée est la barrière ; les contrôles de sanity relèvent de la régression.

Faut-il exécuter les tests de fumée en production, et est-ce sans risque ?

Oui. L'exécution post-déploiement doit cibler l'environnement que les utilisateurs atteignent réellement, y compris la production, car les défaillances de déploiement n'apparaissent que là. Sécurisez-la en utilisant un compte de test dédié et préalimenté, fourni via les secrets de la CI, en limitant les vérifications à une connexion et à des requêtes en lecture seule, et en excluant tout ce qui écrit des données ou envoie des e-mails. Si une écriture est inévitable, cantonnez-la à un tenant de test et nettoyez-la dans le même script.

Puis-je écrire un test de fumée avec Playwright ou Cypress plutôt qu'en script shell ?

Oui, à condition de respecter les mêmes règles : lire l'URL de base depuis une variable d'environnement, assertionner des statuts exacts ou des éléments visibles, et se terminer en quelques secondes. Les runners de navigateur ajoutent du temps de démarrage et de chargement de page à chaque vérification : limitez donc la suite de fumée navigateur à un ou deux parcours et laissez les vérifications HTTP à curl. Placez la spec de fumée dans son propre fichier afin que la CI puisse l'exécuter indépendamment du reste de la suite.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — self-hosted, with full data ownership.

Star on GitHub

We use cookies to improve your experience. By using our site, you accept cookies.