Cypress testing : le guide d'une équipe qui exploite des tests E2E en production

Les tutoriels s'arrêtent au premier test qui passe. Le travail commence après : les tests qui échouent un jour sur trois sans raison, les captures d'écran que personne ne compare, la suite qui se reconnecte à chaque test. Voici ce que nous avons appris en industrialisant tout cela.

Aug 17, 2026

Six fenêtres de navigateur testées selon une planification répétée, cinq au vert et une montrant une différence visuelle détectée

La plupart des articles sur Cypress s'arrêtent au même endroit : l'installation, un premier test qui passe, une capture d'écran de l'interface. C'est utile et c'est très incomplet, parce que le travail réel commence après. Un test qui passe sur votre machine ne dit rien de ce qui se passera quand la suite tournera sans surveillance, sur un environnement partagé, à trois heures du matin.

Nous exploitons des tests end-to-end sur six applications en continu : une configuration, une image de conteneur, une tâche planifiée par application, exécutée contre l'environnement de préproduction de chacune. Nous avons commencé avec un harnais maison écrit en Go, puis nous sommes passés à Playwright. Cet article couvre les bases de Cypress, la comparaison honnête avec ses concurrents, et surtout les cinq choses que nous aurions aimé savoir avant.

Sommaire


Qu'est-ce que Cypress ?

Cypress est un outil de test end-to-end pour applications web. Il pilote un vrai navigateur et vérifie ce que l'utilisateur voit réellement : un formulaire qui se soumet, un prix qui s'affiche correctement, une redirection qui aboutit là où elle doit.

La différence avec les générations précédentes d'outils tient en un mot : l'attente automatique. Un test Cypress qui cherche un bouton attend que ce bouton existe et soit cliquable, dans une limite de temps, au lieu d'échouer immédiatement parce que la page n'a pas fini de charger. Cela paraît anecdotique. C'est en réalité ce qui supprime la principale cause d'échecs aléatoires, ceux qui font qu'une équipe finit par ignorer sa propre suite de tests.

Un test ressemble à ceci, et sa lisibilité est un argument réel :

it('applique la remise palier au bon volume', () => {
  cy.visit('/devis/nouveau')
  cy.get('[data-testid="quantite"]').type('250')
  cy.contains('Remise appliquée').should('be.visible')
  cy.get('[data-testid="total"]').should('contain', '1 875')
})

Cypress est-il meilleur que Selenium ?

Pour une application web moderne, dans la plupart des cas oui, et pour une raison technique précise.

Selenium pilote le navigateur depuis l'extérieur, à travers un protocole. Il envoie une commande, attend une réponse, et n'a aucune idée de ce que la page est en train de faire entre les deux. C'est pour cela que les suites Selenium finissent remplies de temporisations manuelles, ces sleep(2) que tout le monde a écrits un jour et que personne n'assume.

Cypress s'exécute dans le contexte de la page. Il sait quand le DOM change et quand il est stable. Le résultat mesurable, c'est le taux d'échecs aléatoires.

Selenium garde deux avantages qu'il faut reconnaître : une couverture de navigateurs et de langages plus large, et le poids de l'existant. Si votre équipe maintient déjà quatre cents tests Selenium qui fonctionnent, le bon choix technique n'est pas de tout réécrire.

Cypress ou Playwright : pourquoi nous avons choisi Playwright

Voici le passage où nous devons être honnêtes, parce que vous cherchiez Cypress et que nous n'utilisons pas Cypress sur notre propre parc.

Les deux outils partagent l'idée essentielle, l'attente automatique, et Cypress reste un très bon choix. Trois différences ont pesé dans notre cas, et elles n'apparaissent que lorsqu'on dépasse une application unique.

Plusieurs applications dans une seule configuration. Playwright permet de déclarer chaque application comme un « projet » distinct, avec son propre répertoire de tests et sa propre URL de base. Nos six applications vivent donc dans un seul dépôt, une seule image de conteneur, une seule commande. Ajouter une application, c'est ajouter un dossier, pas un dépôt et une chaîne de déploiement.

La comparaison visuelle intégrée. Playwright compare une capture d'écran à une référence et échoue si l'écart dépasse un seuil que vous fixez. Avant cela, nous produisions des captures que personne ne regardait jamais, ce qui est une forme coûteuse de faire semblant.

La sortie du harnais maison. Notre première génération de tests était écrite en Go avec chromedp, pilotée à la main. Elle passait l'essentiel de son temps à lutter contre une catégorie d'instabilité que l'attente automatique de Playwright a simplement supprimée. Ce n'est pas un reproche fait à chromedp, c'est le constat qu'écrire soi-même sa gestion d'attente est un projet à part entière.

Sur une application unique, avec une équipe qui connaît déjà Cypress, la différence ne justifie pas une migration. Nous le disons parce que c'est vrai, pas par prudence.

Cypress est-il facile à apprendre ?

Oui pour le premier test, et cette facilité est un piège.

La syntaxe est lisible, la documentation est bonne, un développeur qui connaît JavaScript écrit son premier test en une heure. Ce qui demande de l'expérience arrive après : l'authentification, l'isolation des données, la tolérance des comparaisons visuelles, l'exécution sans surveillance. C'est exactement le sujet de la section suivante, et c'est là que les projets échouent, pas sur la syntaxe.

Les cinq pièges de l'industrialisation

Ces cinq points viennent de notre configuration réelle. Ils s'appliquent à Cypress comme à Playwright, parce que ce sont des problèmes d'exploitation et non des problèmes d'outil.

1. Le parallélisme casse vos données avant de casser vos tests. L'exécution en parallèle est le premier réglage que l'on active pour gagner du temps, et c'est souvent une erreur. Nos tests créent des lignes dans une base de préproduction partagée : deux tests simultanés se marchent dessus et échouent pour une raison qui n'a aucun rapport avec le code testé. Nous tournons donc avec un seul worker par défaut, et le parallélisme est une décision prise application par application, une fois vérifié que ses données le supportent.

2. Un .only oublié réduit silencieusement votre couverture. Pendant le développement, on isole un test pour aller vite. Si ce marqueur part en intégration continue, la suite ne lève aucune erreur : elle exécute un test, passe au vert, et vous croyez avoir vérifié six applications. Playwright et Cypress savent tous deux interdire ce marqueur en environnement d'intégration. C'est une ligne de configuration et elle évite un faux sentiment de sécurité, ce qui est pire que pas de tests du tout.

3. Une comparaison visuelle à tolérance zéro échoue en permanence. L'anticrénelage et le rendu des polices diffèrent d'une machine à l'autre. Une capture produite sur un poste de développement macOS ne sera jamais identique au pixel près à celle produite dans un conteneur Linux. Nous autorisons un écart de 2 % des pixels avant de déclarer un échec, et nous capturons les références sur l'image de conteneur qui fait foi, pas sur un poste.

4. Se reconnecter à chaque test coûte cher et déclenche les limitations. La tentation est d'écrire la connexion dans une étape exécutée avant chaque test. Sur une suite de cinquante tests, cela fait cinquante connexions, une lenteur inutile et parfois un blocage par le mécanisme anti-abus de votre propre application. La bonne forme est de se connecter une fois par rôle, sauvegarder l'état de session, et le réutiliser dans tous les tests.

5. Les captures d'écran ne servent que si elles sortent du conteneur. Une exécution planifiée dans un conteneur produit des artefacts qui disparaissent avec le conteneur. Il faut décider où ils vont. Nous capturons une image pour chaque test, réussi ou échoué, parce que la capture est la moitié de l'intérêt de l'exercice, et nous ajoutons la trace d'exécution uniquement sur les échecs, parce qu'elle est lourde.

Faire tourner les tests en continu, pas seulement en intégration continue

C'est l'usage le plus sous-estimé des tests end-to-end, et presque personne n'en parle.

Une suite E2E déclenchée par un changement de code répond à la question « est-ce que j'ai cassé quelque chose ». Une suite E2E déclenchée par une horloge répond à une question différente et souvent plus utile : « est-ce que quelque chose a cassé sans que personne n'y touche ». Un certificat expiré, une dépendance externe qui modifie son comportement, une migration appliquée à la main un vendredi soir, un quota atteint.

Nous exécutons la nôtre en tâche planifiée sur Kubernetes, une par application, pointée sur l'environnement de préproduction correspondant. Le résultat est autant de la surveillance synthétique que du test : les captures d'écran et le rapport survivent à l'exécution, et un humain peut les ouvrir le lendemain matin.

Le coût de mise en place est faible quand la suite existe déjà. C'est le même conteneur, avec un déclencheur différent.

Quand Cypress est le bon choix

Nous préférons le dire clairement plutôt que de conclure sur notre propre outil.

Cypress est le bon choix si vous testez une application web, que votre équipe écrit du JavaScript, et que vous voulez la meilleure expérience de mise au point du marché : son mode interactif, qui rejoue le test étape par étape dans le navigateur, reste plus agréable que celui de ses concurrents.

Playwright devient le bon choix dès que vous avez plusieurs applications à couvrir dans un même dispositif, un besoin réel de tester sur WebKit, ou l'intention de faire de la comparaison visuelle sérieuse.

Aucun des deux n'est le bon choix si vous n'avez pas encore de tests unitaires ni d'intégration. Les tests end-to-end sont les plus lents et les plus fragiles : ils couvrent les parcours dont une panne coûte de l'argent, pas la logique métier ligne à ligne. Commencer par le haut de la pyramide donne une suite lente qui échoue souvent, et une équipe qui apprend à l'ignorer.


Si vous avez une application en production sans filet de tests, le sujet n'est pas vraiment l'outil : c'est de savoir sur quels parcours une panne vous coûte de l'argent. C'est le premier livrable de notre audit de code, et c'est aussi ce que nous mettons en place quand nous reprenons une application dont personne ne connaît plus les limites.