A propos Compétences Expérience Services Blog Contact

Ta suite de tests est verte et ton produit est cassé Your test suite is green and your product is broken

Ma suite de tests était verte depuis des semaines. Le parcours principal du produit était cassé.

TL;DR : un test vert ne prouve que ce qu'il vérifie vraiment. J'ai vécu les deux pires cas. Un test de base de données vert sur un changement qui a cassé la prod. Le test tournait avec tous les droits, la prod non. Et une suite de tests d'interface verte sur un produit cassé, parce qu'elle vérifiait les réponses du serveur au lieu de l'écran. À l'heure où l'IA écrit 42 % du code, vérifier est devenu plus dur qu'écrire. Voici les règles que j'applique depuis.

Cet article est pour les devs et les leads qui font confiance à leur CI verte. La CI, c'est la machine qui rejoue tous les tests à chaque changement de code.

Le contexte

Un projet perso, mais de taille réelle. Des services en Go, une base Postgres, un hébergement Kubernetes.

Les tests y sont de deux familles. Les tests d'intégration vérifient un service contre une vraie base de données. Les tests E2E, de bout en bout, pilotent un vrai navigateur sur le vrai produit, comme le ferait un utilisateur.

Une partie du code est écrite avec des agents IA, puis relue. Deux incidents m'ont appris la même leçon, à deux étages différents. Un test vert est nécessaire. Il n'est pas suffisant.

Le test vert qui a cassé le déploiement

Une migration est un script qui modifie la structure de la base de données. Elle se joue toute seule, au déploiement.

La migration d'un nouveau service contenait une ligne de trop : une commande qui change les droits d'un compte de la base.

En production, la migration tourne avec un compte aux droits limités. C'est voulu, par sécurité. Postgres a donc refusé la commande : ce compte n'a pas le droit de changer des droits.

La suite est une cascade. L'outil de migration marque la base « en erreur ». Le service redémarre en boucle sans jamais démarrer. Réparation à la main, avec le compte administrateur.

Le pire n'est pas la panne. Le pire, c'est que le test était vert. Ce test lance une base jetable dans un conteneur, avec un outil nommé Testcontainers. Et dans cette base de test, le compte est administrateur. Tous les droits.

ALTER ROLE app_system BYPASSRLS;
-- la commande qui change les droits d'un compte

-- test : superuser        → OK
-- prod : restricted role  → permission denied
-- schema_migrations.dirty = true → CrashLoopBackOff

La commande interdite passait donc en test et cassait en prod. J'ai vérifié : le test était vert sur la version cassée et sur la version corrigée. Un test qui passe des deux côtés d'un bug ne teste rien.

La règle depuis. Le compte utilisé par le test a les mêmes droits que celui de la prod. Et une migration ne touche jamais aux comptes, seulement aux tables.

Une suite E2E verte sur un produit cassé

Deuxième incident, plus embarrassant. Pendant des semaines, un parcours entier était cassé. Un dossier créé, un document signé, et l'écran suivant n'affichait plus rien de bon.

La suite E2E ? Cent pour cent verte, tous les jours.

J'ai audité la suite pour comprendre. Presque la moitié des tests n'ouvraient jamais de navigateur. Ils appelaient l'API, l'interface du serveur, et vérifiaient sa réponse brute. Personne ne regardait l'écran.

Un raccourci de test sautait l'étape de signature. L'étape même que ces tests prétendaient couvrir. Et les tests du vrai parcours de signature étaient marqués « à corriger plus tard ». Tous.

Dit autrement : le front pouvait cesser d'afficher l'état du dossier, les montants, le bouton suivant. Cent pour cent des tests passaient quand même.

Vérifie ce que l'utilisateur voit, pas ce que le serveur répond

La réécriture de la suite tient en une règle. Vérifie ce qui s'affiche à l'écran. Jamais la réponse brute du serveur.

Pourquoi ? Entre le serveur et l'écran, il y a tout le front : le code qui transforme la réponse en pixels. C'est lui qui était cassé. Et aucun test ne le regardait.

Deux détails qui paient. Vérifier chaque écran dans les deux langues du produit attrape les textes manquants, affichés en codes bruts. Et si tu compares des captures d'écran, génère-les toujours sur la même machine : le rendu du texte change d'une machine à l'autre.

Un raccourci sur le chemin testé est un mensonge

Le raccourci de signature mérite sa propre section. Il existait pour une bonne raison : la vraie signature est lente et dépend d'un service externe.

Mais un test de signature qui saute la signature ne teste pas la signature. Il teste que le raccourci marche. C'est un mensonge, bien rangé dans le code.

Et il cachait plus grave. Dans ce produit, la fin de signature déclenche un événement. Cet événement met à jour les états, envoie les notifications, ouvre le fil de discussion. Le raccourci ne déclenchait jamais cet événement. L'état qu'il fabriquait ressemblait au vrai, sans l'être.

La règle de réécriture : prépare les données par l'API pour aller vite, d'accord. Mais la chose testée, elle, n'est jamais simulée. Le test de signature signe pour de vrai, dans le vrai module, jusqu'au bout.

2026 : le plus dur n'est plus d'écrire le code, c'est de le vérifier

Pourquoi en parler maintenant ? Parce que le volume a changé de camp.

D'après l'enquête State of Code de Sonar, 42 % du code commité aujourd'hui est généré ou assisté par IA. 96 % des devs disent ne pas lui faire entièrement confiance. Et pourtant, moins d'un sur deux vérifie systématiquement ce code avant de le valider.

Les tests encaissent le choc. New Relic rapporte que 78 % des organisations voient plus d'incidents en production depuis l'arrivée du code généré. CodeRabbit mesure 1,7 fois plus de problèmes dans ce code, et 75 % d'erreurs de logique en plus.

Mes deux incidents racontent la même chose que ces chiffres. Le code s'écrit vite maintenant, les tests aussi. Une suite verte n'a jamais été aussi facile à produire. Et n'a jamais prouvé aussi peu.

La checklist pour tester ta suite de tests

Pose ces questions à ta CI verte. Chacune vient d'un incident réel.

  • Le compte base de données du test a les droits de la prod, pas tous les droits
  • Un test doit échouer sur la version cassée : vérifie-le au moins une fois
  • Les parcours critiques sont vérifiés sur l'écran, pas sur la réponse du serveur
  • Aucun raccourci sur le chemin que le test prétend couvrir
  • Les données préparées par l'API déclenchent les mêmes événements que le vrai parcours
  • Les tests « à corriger plus tard » sont comptés et visibles, pas oubliés
  • Chaque écran est vérifié dans toutes les langues du produit
  • Le code généré par IA passe les mêmes barrières que le tien, sans exception

Ce qu'il faut retenir

Une CI verte est une condition, pas une preuve. La question utile n'est pas « les tests passent-ils ? » mais « qu'est-ce qui casserait sans qu'ils le voient ? ».

Audite ta suite comme tu auditerais du code : cherche ce qu'elle ne regarde pas. Chez moi, la réponse était : le produit.

Tu veux un audit honnête de ta suite de tests, ou des barrières plus dures sur le code généré ? Parlons-en.

My test suite had been green for weeks. The product's main journey was broken.

TL;DR: a green test only proves what it actually checks. I lived through both worst cases. A green database test on a change that broke prod, because the test ran with full rights and prod did not. And a green UI test suite on a broken product, because it checked server responses instead of the screen. Now that AI writes 42% of code, verifying has become harder than writing. Here are the rules I apply since.

This article is for developers and leads who trust their green CI. CI is the machine that replays every test on each code change.

The setup

A personal project, but real-sized. Go services, a Postgres database, Kubernetes hosting.

The tests come in two families. Integration tests check a service against a real database. E2E tests, end to end, drive a real browser on the real product, the way a user would.

Part of the code is written with AI agents, then reviewed. Two incidents taught me the same lesson, at two different layers. A green test is necessary. It is not sufficient.

The green test that broke the deploy

A migration is a script that changes the structure of the database. It runs on its own, at deploy time.

A new service's migration carried one line too many: a command that changes the rights of a database account.

In production, the migration runs under an account with limited rights. That is on purpose, for security. So Postgres refused the command: that account has no right to change rights.

What follows is a cascade. The migration tool marks the database as "dirty". The service restarts in a loop without ever starting. Manual repair, with the administrator account.

The outage is not the worst part. The worst part is that the test was green. That test spins up a throwaway database in a container, with a tool called Testcontainers. And in that test database, the account is an administrator. Full rights.

ALTER ROLE app_system BYPASSRLS;
-- the command that changes an account's rights

-- test : superuser        → OK
-- prod : restricted role  → permission denied
-- schema_migrations.dirty = true → CrashLoopBackOff

So the forbidden command passed in test and broke in prod. I checked: the test was green on the broken version and on the fixed one. A test that passes on both sides of a bug tests nothing.

The rule since. The account the test uses has the same rights as the prod one. And a migration never touches accounts, only tables.

A green E2E suite on a broken product

Second incident, more embarrassing. For weeks, an entire journey was broken. A case created, a document signed, and the next screen showed nothing right.

The E2E suite? One hundred percent green, every day.

I audited the suite to understand. Almost half the tests never opened a browser. They called the API, the server's interface, and checked its raw response. Nobody was looking at the screen.

A test shortcut skipped the signing step. The very step those tests claimed to cover. And the tests of the real signing journey were marked "fix later". All of them.

Put differently: the front end could stop displaying the case state, the amounts, the next button. One hundred percent of the tests still passed.

Check what the user sees, not what the server returns

The suite's rewrite fits in one rule. Check what shows up on the screen. Never the server's raw response.

Why? Between the server and the screen sits the whole front end: the code that turns responses into pixels. That is what was broken. And no test was looking at it.

Two details that pay off. Checking every screen in both product languages catches missing texts, displayed as raw codes. And if you compare screenshots, always generate them on the same machine: text rendering changes from one machine to the next.

A shortcut on the tested path is a lie

The signing shortcut deserves its own section. It existed for a good reason: the real signature is slow and depends on an external service.

But a signing test that skips the signing does not test the signing. It tests that the shortcut works. It is a lie, neatly stored in the codebase.

And it hid something worse. In this product, the end of a signature fires an event. That event updates the states, sends the notifications, opens the discussion thread. The shortcut never fired that event. The state it built looked like the real one, without being it.

The rewrite rule: prepare data through the API for speed, fine. But the thing under test is never faked. The signing test signs for real, in the real module, all the way through.

2026: the hard part is no longer writing code, it is verifying it

Why talk about this now? Because the volume switched sides.

According to Sonar's State of Code survey, 42% of code committed today is AI-generated or assisted. 96% of developers say they do not fully trust it. And yet, fewer than one in two always checks that code before approving it.

Tests absorb the shock. New Relic reports that 78% of organizations see more production incidents since generated code arrived. CodeRabbit measures 1.7 times more issues in that code, and 75% more logic errors.

My two incidents tell the same story as those numbers. Code gets written fast now, tests included. A green suite has never been easier to produce. And has never proven less.

The checklist to test your test suite

Ask your green CI these questions. Each one comes from a real incident.

  • The test's database account has prod rights, not full rights
  • A test must fail on the broken version: verify that at least once
  • Critical journeys are checked on the screen, not on the server response
  • No shortcut on the path the test claims to cover
  • API-prepared data fires the same events as the real journey
  • Tests marked "fix later" are counted and visible, not forgotten
  • Every screen is checked in every language the product ships
  • AI-generated code goes through the same gates as yours, no exceptions

What to remember

A green CI is a precondition, not a proof. The useful question is not "do the tests pass?" but "what would break without them noticing?".

Audit your suite the way you would audit code: look for what it does not look at. In my case, the answer was: the product.

Want an honest audit of your test suite, or harder gates on generated code? Let's talk.