test-fix

Par liferay · liferay-portal

Résoudre un échec de test Liferay de bout en bout.

npx skills add https://github.com/liferay/liferay-portal --skill test-fix

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, Playwright et Poshi). 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 null quand 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 null quand 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 portal et Outdated test, nommez le commit fautif (SHA court et sujet) et ce qu'il a changé.
  • Pour No fix needed, la chaîne littérale Test 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-bug pour 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 label claude-test-fix au 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 Do avec un commentaire contenant le littéral Test 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

  1. 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 pr pour 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 par git 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.

    Quand vous ignorez et que d'autres candidats restent, recommencez avec le suivant.

  2. Invoquez la skill jira-task avec 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 label claude-test-fix.

  3. Invoquez la skill start-work sur 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.properties avec 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ée feature.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 featureFlagsTest sous modules/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} et HEAD adresse déjà l'échec. Quand c'est le cas, terminez avec Verdict: 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 avec Verdict: 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 Unresolved avec une Conclusion ré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é :

  1. Lisez son intention documentée — le message de commit et le diff, le ticket LPD-XXXXX lié (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 merged

    Cherchez 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.

  2. 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).

  3. 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.

Skills similaires