Résoudre un Échec de Test
Résoudre un seul échec de test de bout en bout.
Préconditions
- Tomcat est en cours d'exécution (obligatoire pour
Java Integration,PlaywrightetPoshi). Lancez-le s'il ne l'est pas.
Entrée
Case Result ID
Quand ${ARGUMENTS} est un entier positif, utilisez-le directement comme identifiant de résultat de cas Testray.
URL de Build Testray
Quand ${ARGUMENTS} est une URL de la forme https://testray.liferay.com/#/project/<projectId>/routines/<routineId>/build/<buildId>?filter=<urlencoded-json>, résolvez-la en identifiant de résultat de cas en suivant references/testray.md. La procédure retourne un identifiant de résultat de cas que le reste du workflow consomme de manière identique à celui fourni par l'utilisateur.
Nom du Test
Quand ${ARGUMENTS} est n'importe quoi d'autre, résolvez-le en identifiant de résultat de cas en suivant references/testray.md. Quand la résolution échoue, signalez la raison et demandez à l'utilisateur de recommencer avec l'identifiant de résultat de cas directement.
Données d'Échec
Récupérées au démarrage de l'exécution en suivant references/testray.md, qui couvre l'authentification, la résolution de nom vers ID et comment dériver chaque champ. Quand un nom de test a été passé et que la résolution échoue, signalez la raison et demandez à l'utilisateur de recommencer avec l'identifiant de résultat de cas directement. Quand le résultat du cas est déjà PASSED, ignorez le workflow et terminez avec Verdict: No fix needed. Quand il est BLOCKED — un testeur l'a délibérément signalé, il ne doit donc pas être corrigé automatiquement — ignorez le workflow et terminez en signalant que le cas est bloqué. Sinon, la procédure retourne ces champs :
- buildSha — commit sur lequel la build défaillante a été testée.
- errorTrace — trace d'erreur produite par le framework de test.
- failureDate — horodatage du moment où le résultat du cas a été enregistré, utilisé pour limiter la vérification des tickets dupliqués dans Claim the Failure.
- firstFailSha — premier commit où le test a échoué (peut être
nullquand le cas n'a pas d'historique d'échec enregistré). - lastPassSha — commit où le test a réussi pour la dernière fois (peut être
nullquand le cas n'a pas de réussite récente enregistrée). - name — nom du test (classe, spec ou méthode).
- type — l'un de
Java Integration,Java Semantic Versioning,Java Unit,JavaScript,Playwright,Poshi.
Résultat Attendu
Name
Le nom du test (classe, spec ou méthode) retourné par la récupération Testray. Quand la récupération échoue avant qu'un nom soit connu, utilisez case-result <CASE_RESULT_ID>.
Type
Le type de test retourné par la récupération Testray (l'une des valeurs listées sous Input). Utilisez Unknown quand la récupération échoue avant qu'un type soit connu.
Verdict
L'un de :
Bug in portal— le code produit contenait la correction.No fix needed— le test a réussi localement à la première reproduction ; rien n'a été modifié.Outdated test— le test contenait la correction.Unresolved— l'investigation n'a pas convergé, ou une étape a échoué.
Conclusion
Une phrase décrivant le résultat :
- Pour
Bug in portaletOutdated test, nommez le commit fautif (SHA court et sujet) et ce qu'il a changé. - Pour
No fix needed, la chaîne littéraleTest passes locally. - Pour
Unresolved, un résumé honnête de remise listant les hypothèses considérées, les tentatives faites, les effets observés et la piste restante la plus plausible.
Resolution Time
Le temps écoulé de l'exécution, formaté comme <minutes>m <seconds>s.
Jira Tickets
La Task créée dans Claim the Failure est le ticket persistant de référence pour chaque verdict. Mettez-la à jour à la fin de l'exécution en fonction du verdict :
-
Bug in portal — invoquez la skill
jira-bugpour créer un Bug séparé décrivant la régression. Le titre résume la régression. La description porte le nom du test défaillant, la trace et les étapes de reproduction dérivées du scénario de test. Ne faites pas ajouter le labelclaude-test-fixau Bug — ce label appartient à la Task seule, donc la vérification des tickets dupliqués dans Claim the Failure correspond à un ticket par échec. Liez le Bug à la Task avec le type de lien Fix afin que la Task le surface en tant que is fixed by. Retournez l'URL du Bug à côté de l'URL de la Task. -
Outdated test — retournez l'URL de la Task.
-
No fix needed — fermez la Task en tant que
Won't Doavec un commentaire contenant le littéralTest passes locally. Aucune PR n'est ouverte. -
Unresolved — laissez la Task en In Progress, ajoutez le résumé de remise en tant que commentaire et retournez son URL afin que la personne qui la reprenne dispose d'une page d'atterrissage unique.
Pull Request
Uniquement quand le test a été corrigé (verdict Bug in portal ou Outdated test) : l'URL de la pull request ouverte pour la correction.
Effectuez un commit, puis trouvez le propriétaire des fichiers modifiés en utilisant <repo-root>/.github/CODEOWNERS et invoquez la skill pr avec lui comme dépôt cible. Remplacez la valeur par défaut du titre seul de l'utilisateur et transmettez explicitement le contenu du body afin que la pull request explique la régression.
Utilisez ce modèle. L'URL de navigation sur la première ligne pointe sur le ticket que la skill pr résout (le sous-tâche Technical Task, pas la Task parente), donc les examinateurs atterrissent sur le même ticket où l'URL de la pull request est enregistrée :
https://liferay.atlassian.net/browse/<TICKET>
## Failing Test
`<test-name>`
`<test-path>`
\`\`\`
<errorTrace>
\`\`\`
## Root Cause
Commit `<short-sha>` ("<subject>") <une ou deux phrases>.
## Fix
<un paragraphe expliquant la modification et pourquoi elle fonctionne>.
- `<file-1>`
- `<file-2>`
Workflow
Claim the Failure
-
Vérifiez Jira pour un ticket LPD dont le résumé contient
<test-name>et est labelliséclaude-test-fix. Décidez s'il couvre déjà cet échec par son état :- Unresolved (Open, In Progress ou tout état non résolu) → réclamé, ignorez. Quelqu'un y travaille déjà.
- Resolved → trouvez la PR du ticket en suivant les règles de la skill
prpour l'endroit où elle est enregistrée, dérivez son commit de correction et testez s'il a déjà atteint la build qui a échoué, en jugeant pargit merge-base --is-ancestor <fixSha> <buildSha>:- Le commit de correction est un ancêtre de
<buildSha>→ la correction était déjà présente quand cette build a été exécutée, pourtant le test a toujours échoué, donc elle ne couvre pas cette occurrence → procédez. - Le commit de correction n'est pas encore dans
<buildSha>→ Testray n'a pas rétesté depuis la fusion de la correction, donc l'échec est déjà adressé → ignorez. - Aucun commit de correction trouvé (ticket test seulement, commit non fusionné ou résolution non corrective) → revenez à la date de résolution : résolu avant
<failureDate>procédez, résolu sur ou après ignorez.
- Le commit de correction est un ancêtre de
Quand vous ignorez et que d'autres candidats restent, recommencez avec le suivant.
-
Invoquez la skill
jira-taskavec le résumé<test-name>et une description qui nomme l'identifiant de résultat de cas, la build source et l'extrait de trace d'échec. Ajoutez le labelclaude-test-fix. -
Invoquez la skill
start-worksur la nouvelle Task.
Reproduce Locally
Cette étape s'exécute avant toute analyse de plage ou de commit. Le test peut déjà réussir localement — quand c'est le cas, l'exécution se termine ici sans investigation supplémentaire.
Set Feature Flags
Inspectez la source du test pour découvrir les drapeaux de fonctionnalité dont il dépend. Reflétez la configuration CI avant de reproduire. Sinon, le chemin du test diffère.
-
Les tests Poshi exigent des drapeaux dans
<bundles>/portal-ext.propertiesavec Tomcat redémarré pour les récupérer. Avant de modifier le fichier pour la première fois dans cette exécution, prenez un instantané pour pouvoir le restaurer plus tard. Ensuite, supprimez chaque entréefeature.flag.*existante et ajoutez uniquement les drapeaux que le test exige — le fichier doit se terminer avec les drapeaux du test et rien d'autre, donc les drapeaux non liés restants des exécutions précédentes ne peuvent pas interférer. L'instantané original est restauré plus tard dans Restore the Portal. Redémarrez Tomcat pour que les nouvelles valeurs de drapeaux prennent effet. -
Les tests Playwright déclarent les drapeaux via la fixture
featureFlagsTestsousmodules/test/playwright/fixtures. La fixture les bascule par test — aucune modification du portail n'est nécessaire.
Run the Test
Exécutez le test, en déployant d'abord quand le type l'exige. Pour Java Semantic Versioning, le « test » est <gradlew> baseline depuis le module défaillant — strictement une vérification de contrat API, pas un test comportemental. Pour les types de test qui exercent le runtime (Java Integration, Playwright, Poshi), lisez également le journal du serveur après l'exécution ; il capture les exceptions côté portail, les erreurs de déploiement et les traces de pile qui n'atteindront jamais errorTrace, et nomme fréquemment l'échec réel. Puis comparez le résultat local avec errorTrace :
- Le test réussit → vérifiez si un commit entre
${FIRST_FAIL_SHA}etHEADadresse déjà l'échec. Quand c'est le cas, terminez avecVerdict: No fix needed. Sinon, raisonnez sur les raisons pour lesquelles le test a échoué en CI (le test peut être instable ou échouer pour des raisons d'environnement). Essayez de le corriger et réexécutez pour confirmer. Quand aucune cause plausible ne se dessine, terminez avecVerdict: No fix needed. Ignorez Identify Suspect Commits et Iterate Through Suspects dans tous les cas. - Même échec → continuez vers Identify Suspect Commits.
- Échec différent → signalez la différence et demandez à l'utilisateur s'il faut continuer. Quand l'utilisateur est injoignable ou refuse, marquez l'échec comme
Unresolvedavec uneConclusionrésumant les deux traces (celle retournée par la récupération Testray et celle observée localement) et terminez.
Identify Suspect Commits
Le changement cassant se situe entre ${LAST_PASS_SHA} et ${FIRST_FAIL_SHA}. Listez les candidats à partir du diff entre ces deux commits, puis affinez en traçant l'historique des lignes du fichier possédant la ligne la plus proche de l'assertion défaillante ou du cadre le plus haut dans errorTrace.
Quand cela ne pointe pas vers un seul commit, classez les candidats : fichiers du propre module du test d'abord, puis modules dont les packages sont importés par le test, puis *-api / portal-kernel / infrastructure partagée frontend-js-*, puis portal-impl / petra-* / infrastructure partagée.
Iterate Through Suspects
Appliquez les correctifs candidats comme des modifications non validées ; l'étape Pull Request les valide plus tard. Pour chaque suspect dans l'ordre classé :
-
Lisez son intention documentée — le message de commit et le diff, le ticket
LPD-XXXXXlié (résumé, type de ticket, description) quand le sujet en porte un, et le body de la pull request fusionnée qui a introduit le commit :gh pr list --json number,title,body --repo brianchandotcom/liferay-portal --search "<sha>" --state mergedCherchez des références explicites au test défaillant ou au comportement affirmé, et tout signe que le changement abandonne délibérément le contrat que l'assertion vérifiait.
-
Appliquez une correction qui touche les sections du suspect. La correction doit vivre dans le diff entre
${LAST_PASS_SHA}et${FIRST_FAIL_SHA}— c'est le seul endroit où la régression peut vivre, et une correction en dehors de cette plage signifie que le diagnostic est faux. N'escaladez jamais la portée de la correction pour forcer la convergence. Adaptez le test (Outdated test) — notamment en supprimant, affaiblissant ou@Ignore-ant une assertion — uniquement quand la documentation du commit fautif (sujet, ticket Jira lié ou body de PR) énonce explicitement le changement de contrat que l'assertion vérifiait ; sans cette justification documentée, l'assertion est correcte et la régression vit dans le code produit (Bug in portal). -
Réexécutez le test.
Quand le test devient vert, ne verrouillez pas le verdict immédiatement — continuez à lire les suspects restants pour confirmer qu'aucun d'eux n'est une meilleure explication. Fixer le premier correctif vert est comment un mauvais correctif se fait livrer ; validez uniquement quand aucun meilleur candidat ne se dessine.
Quand l'ensemble actuel de candidats est épuisé sans vert, élargissez-le (fichiers de rang suivant, infrastructure) et itérez à nouveau — jusqu'à trois tours. Après la troisième tour sans convergence, ou quand les candidats sont épuisés, marquez l'échec comme Unresolved avec une Conclusion listant les suspects analysés, les tentatives faites, ce que chacun a changé à propos de l'échec et la piste restante la plus plausible. Exécutez le nettoyage dans Restore the Portal et terminez.
Une fois le verdict verrouillé (uniquement après une exécution locale verte — ne validez jamais ni n'ouvrez une PR sinon), enregistrez le commit fautif (SHA court + sujet) et une phrase expliquant comment il a cassé le test — réutilisée dans la section Root Cause du body de PR (voir Pull Request).
Restore the Portal
Cette étape est idempotente : le portail doit terminer l'exécution dans le même état qu'il a commencé — Tomcat en cours d'exécution avec le portal-ext.properties original chargé.
Quand Set Feature Flags a modifié <bundles>/portal-ext.properties, restaurez l'instantané et redémarrez Tomcat pour récupérer les propriétés originales.
Quand Set Feature Flags a été ignoré parce que le test n'a pas besoin de changements de drapeaux, Tomcat reste en cours d'exécution intact et il n'y a rien à faire.