Aller au contenu
IA — claude code — playwright — QA

Tests E2E Playwright filmés par Claude Code : filmer est facile, prouver ne l'est pas

Le QA d'un client exige une vidéo de recette par ticket. J'ai confié la prise de vue à un skill Claude Code : il propose le scénario, filme le test Playwright et dépose la vidéo sur Jira. Deux leçons : prouver est plus dur que filmer, et un skill doit être pensé pour s'améliorer à l'usage.

Pellicule de film dont les images montrent un curseur qui s'approche d'un bouton orange, validé par une coche dans la dernière image.
Des tests E2E Playwright filmés par Claude Code, du parcours à la preuve

Ces vidéos de recette servent de preuve qu'une fonctionnalité a bien été testée avant d'être validée. Tournées à la main, elles me prenaient environ 30 minutes chacune, et surtout me mobilisaient pendant tout le test. Le skill Claude Code qui les tourne aujourd'hui a été construit en deux heures. J'en ai produit une cinquantaine avec lui, puis tous les développeurs du projet, une dizaine, l'ont adopté.

La conclusion d'abord : le gain de temps est réel, mais ce n'est pas le plus instructif. Deux leçons ressortent.

La première : filmer un test E2E est facile, en faire une preuve fiable ne l'est pas. Une vidéo qui montre le mauvais code, ou qui est déposée sur le mauvais ticket, est pire que l'absence de vidéo.

La seconde : un skill doit être pensé pour s'améliorer à l'usage. Ici, chaque sélecteur difficile qu'un développeur résout est consigné dans un fichier partagé, que le skill relit avant chaque test. En un peu plus de trois mois, 43 entrées s'y sont accumulées.

Filmer ses tests E2E à la main : le coût n'est pas que le temps

Une vidéo de recette tournée à la main, c'est un enregistreur d'écran, un scénario déroulé sans hésitation, et une prise à refaire à la moindre erreur : un mauvais clic, un champ oublié, une donnée absente de la base.

Le temps n'est pourtant pas le principal problème. Pendant toute la prise de vue, je ne faisais rien d'autre : connaître le parcours par cœur, surveiller l'écran, recommencer si la démonstration n'était pas propre. C'est beaucoup d'attention pour une tâche qui n'apporte aucune information nouvelle, puisque le parcours est connu d'avance et que le test pourrait être joué par une machine.

Du ticket Jira à la vidéo de recette avec Claude Code

Le skill enchaîne sept étapes, du ticket au dépôt de la preuve.

  1. Il déduit la clé du ticket de la branche Git courante, et récupère la user story (US) parente si le ticket est une sous-tâche.
  2. Il lit les critères d'acceptation, puis explore le code du périmètre pour repérer les routes, les libellés et les champs réels. Il cherche aussi lui-même le jeu de données le plus adapté, par des requêtes SQL ou des appels d'API sur l'environnement de développement.
  3. Il propose un scénario numéroté dont chaque étape est observable à l'écran, et marque d'une étoile les actions, une à trois, qui portent vraiment la fonctionnalité.
  4. Le développeur valide ou ajuste le scénario avec lui, avant toute ligne de code.
  5. Il écrit le test Playwright, avec des assertions sur les résultats clés, et le fait passer au linter.
  6. Il joue le test, ce qui produit la vidéo en une à deux minutes.
  7. Il peut déposer la vidéo en pièce jointe du ticket, avec un commentaire structuré : scénario joué, valeurs de test, requêtes SQL de vérification, constats.

Un scénario proposé ressemble à ceci (exemple fictif) :

Scénario proposé : PROJ-123
Route de départ : /commandes

1. Ouvrir le filtre "Statut" et choisir "En attente" : la liste se met à jour
2. ⭐ Cliquer sur "Exporter la sélection" : le fichier se télécharge
3. Vérifier le message "Export terminé"

La validation du scénario est l'étape qui conditionne la preuve. C'est le développeur qui sait ce que le ticket doit prouver, et c'est à ce moment qu'il choisit les étapes à mettre en valeur. Une fois le scénario validé, le reste tourne en général sans lui : il passe à autre chose pendant que la vidéo se génère. De bout en bout, c'est de l'ordre de quelques minutes.

Chaîne d'une vidéo de recette, du ticket Jira au dépôt de la preuve, avec ses points de contrôle.
Le développeur n'intervient qu'une fois, pour valider le scénario ; les contrôles bloquent avant de filmer et avant de déposer.

Rendre une vidéo de test Playwright lisible

Playwright sait enregistrer une vidéo de chaque test, mais la vidéo brute se lit mal. En mode headless, il n'y a pas de curseur, et Chromium ne filme jamais le curseur du système, même en mode visible. Les clics sont instantanés : un bouton change d'état sans qu'on voie qui l'a déclenché.

Le skill corrige cela avec quelques fonctions partagées par tous les tests :

  • Un curseur injecté dans la page, un simple élément qui suit les événements mousemove ;
  • Un déplacement animé vers chaque cible, sur une trajectoire légèrement courbe avec accélération puis ralentissement ;
  • Pour les étapes marquées d'une étoile, une à trois boucles du curseur autour de l'élément avant le clic ;
  • Une fausse barre d'adresse en haut de la page, car la vidéo ne filme que le contenu et pas le navigateur ; elle sert à prouver les fonctionnalités liées à l'URL ;
  • Un ralenti de 500 ms entre les actions, et la dernière image tenue deux secondes.

L'animation tourne dans le navigateur, en requestAnimationFrame, et non côté Playwright. Sinon, chaque petit déplacement subirait le ralenti configuré, et le curseur avancerait par saccades.

Leçon 1 : un test E2E filmé n'est pas encore une preuve

La question est plutôt : qu'est-ce qui garantit que la vidéo montre bien le code du ticket ? Un QA qui voit une vidéo propre valide le ticket. Si la vidéo montre en réalité le comportement d'avant la modification, le bug passe pour testé et personne n'y revient : une preuve fausse clôt la question, là où une preuve absente la laisse ouverte.

Le contexte compte : chaque développeur fait tourner le backend et le frontend sur son poste, et la vidéo filme ce qui y tourne. Après la création du skill, l'équipe lui a ajouté un outillage de recette : quelques scripts qui démarrent cet environnement et déposent la preuve. Ce sont eux qui portent les contrôles. On peut filmer le mauvais code de plusieurs façons : un backend compilé avant le dernier commit, deux branches ouvertes en parallèle dans deux worktrees Git, un fichier de connexion qui pointe encore vers l'autre. Les scripts refusent donc de continuer dans chacun de ces cas plutôt que de produire une vidéo fausse.

SituationCe qu'on risqueraitRéaction de l'outil
Backend compilé plus ancien que son dernier commit, ou qu'une modification en coursFilmer le comportement d'avant l'USRefuse de démarrer le backend
Frontend lancé depuis un autre worktreeFilmer la branche d'un autre ticketRefuse de l'utiliser
Adresse de connexion qui mène à un autre frontendOuvrir la session sur l'autre brancheRefuse d'ouvrir la session
Session expirée pendant le testFilmer une page de connexionFait échouer le test
Vidéo du même test déjà rangéeÉcraser la preuve précédenteRange la nouvelle sous un autre nom
Pièce jointe dont le nom ne porte pas la clé du ticketDéposer une preuve sur le mauvais ticketRefuse l'envoi
Commentaire qui ne cite que d'autres ticketsPublier le texte d'une autre USRefuse l'envoi
Remplacement ou suppression d'un élément d'un autre ticketDétruire la preuve d'un autre ticketRefuse avant toute destruction

On peut forcer le passage quand on sait ce qu'on fait : la plupart des contrôles se contournent avec une option dédiée, qui affiche le refus dans la sortie. Et les scripts sont couverts par des tests automatisés, pour qu'une modification ne casse pas un contrôle sans qu'on le voie.

Tout n'est pas bloqué pour autant. Si le backend a été lancé depuis l'IDE, l'outil ne peut pas savoir quand il a été compilé : il prévient, mais laisse passer. Même chose pour un frontend lancé à la main. Et pour vérifier qu'une pièce jointe part sur le bon ticket, l'outil se fie au nom du fichier.

Enfin, le test lui-même sert de contrôle. Chaque scénario vérifie les résultats clés : si le message attendu n'apparaît pas, le test échoue. On corrige alors, le test ou le code, et on rejoue avant de déposer quoi que ce soit.

Leçon 2 : un skill de tests E2E qui apprend du design system, avec toute l'équipe

La règle de départ du skill est simple : ne jamais inventer un sélecteur, toujours le dériver du code réel des composants. Elle ne suffit pas. Le design system du client repose sur des Web Components, et leur DOM dans un vrai navigateur ne ressemble pas à celui des mocks utilisés par les tests unitaires. Un sélecteur qui passe en test unitaire ne dit rien de son comportement dans Playwright.

Quelques cas rencontrés :

  • Une modale dont l'élément hôte mesure 0 px de haut, tout son rendu étant dans le shadow DOM : Playwright la juge toujours masquée, et un test qui vérifie sa visibilité échoue alors qu'elle est ouverte ;
  • Un champ avec masque de saisie que fill() laisse vide : la soumission est bloquée sans aucune erreur visible, il faut taper les caractères un par un ;
  • Une case à cocher dont l'état est porté par un attribut du composant, et l'état désactivé par l'input interne seulement ;
  • Un menu déroulant dont les options n'ont pas le rôle option, et sont rendues dans une liste flottante ajoutée à la fin du document, loin du composant.

Le premier cas donne une idée de la correction, en version générique :

// Échoue toujours : l'hôte mesure 0 px, même modale ouverte
await expect(page.locator('app-modal')).toBeVisible();

// Preuve fiable : un élément rendu à l'intérieur, comme le titre
const modale = page.locator('app-modal');
await expect(modale.getByRole('heading', { name: 'Modifier la commande' })).toBeVisible();

Quand un sélecteur échoue, le skill écrit un test jetable pour inspecter le DOM réel, trouve le bon sélecteur, puis consigne la solution dans un README de recettes qu'il relit avant chaque nouveau test. Les tests de recette eux-mêmes sont versionnés, et servent de modèles pour les tickets suivants.

Ce README est versionné dans le dépôt du projet. Le skill a d'abord servi aux deux développeurs front, puis à la dizaine de développeurs du projet : la solution trouvée par l'un sert à tous. L'autre développeuse front a d'ailleurs contribué à l'améliorer dès ses premiers jours. Depuis le premier commit du README, le 17 juin, 43 entrées s'y sont accumulées, soit environ trois par semaine. La plupart concernent des sélecteurs du design system, quelques-unes des règles de contexte (droits d'accès, routes). Le revers : le fichier dépasse déjà 700 lignes, que le skill relit avant chaque test.

Boucle d'amélioration d'un skill Claude Code : chaque sélecteur résolu est consigné pour la vidéo suivante.
Un sélecteur résolu par un développeur est relu par le skill avant chaque test suivant, pour toute l'équipe.

Ce qu'une vidéo de recette ne remplace pas

La vidéo ne montre qu'un parcours : c'est toujours le QA qui juge si le comportement filmé est le bon. Le skill ne dispense pas non plus de lire le ticket : c'est parce que le développeur valide le scénario que la vidéo prouve la bonne chose.

Il reste aussi des contraintes pratiques. Les données de test doivent exister dans la base de développement : le skill les cherche lui-même, et prévient quand il ne trouve rien d'adapté. La session de connexion expire au bout de 20 à 30 minutes, ce qui oblige à la rouvrir entre deux séries de vidéos.

Ce qu'il faut retenir

  • Une vidéo de test n'est une preuve que si elle montre le bon code et arrive sur le bon ticket. Contrôlez la fraîcheur du build, la branche et la destination avant de filmer, et préférez un refus à une vidéo fausse.
  • Faites valider le scénario par le développeur avant de générer le test. C'est lui qui sait ce que le ticket doit prouver, et les étapes à mettre en valeur en découlent.
  • Faites en sorte qu'un skill s'améliore à chaque usage : donnez-lui un endroit où consigner ce qu'il apprend, versionné et partagé par l'équipe. Sur ce projet, 43 entrées en un peu plus de trois mois.
  • Mesurez le gain sur la disponibilité du développeur autant que sur le chronomètre : pendant que la vidéo se génère, il travaille sur autre chose.

Sources

Dernier