Réussite ou échec ne suffit pas : comment 14 verdicts sont décidés
Un test rouge devrait signifier que l'application est défaillante. Lorsque le rouge peut aussi vouloir dire que le DNS a vacillé, que le site a affiché un CAPTCHA ou que le navigateur s'est arrêté brutalement, l'équipe apprend à relancer les tests en échec au lieu de les analyser, et le véritable défaut reste masqué par le bruit. Nexus Studio attribue à chaque exécution l'un des 14 verdicts au lieu de deux. Cette page explique comment le moteur en sélectionne un, selon l'ordre dans lequel il tranche, et où se trouvent les limites de la méthode.
Par l'équipe Nexus Studio, Verdict System LLC. 7 octobre 2026.
Quels sont les 14 verdicts ?
Les 14 verdicts sont SECURE, CHAOS_RESILIENT, AUTO_RECOVER, FLAKY, PERFORMANCE_DEGRADED, A11Y_VIOLATION, SECURITY_VIOLATION, BREACHED, BREACHED_FLAKY, CHAOS_BREACHED, TIMEOUT, UNREACHABLE, BLOCKED et CRASHED. Ils se divisent en quatre groupes : réussi, réussi avec réserve, l'application a échoué, et aucun verdict sur l'application car l'environnement ou le banc d'essai est en cause.
Comment le moteur détermine-t-il un verdict ?
Le moteur pose trois questions, dans cet ordre :
- Le test a-t-il produit un résultat ?
- S'il a réussi, s'est-il déroulé de manière totalement fluide ?
- S'il a échoué, à qui la faute : au banc de test, à l'environnement ou à l'application ?
Une seule réponse constitue un rapport de bug : une défaillance incombant à l'application. Toute autre réponse constitue une information sur autre chose, et reçoit une désignation explicite en conséquence.
Quand un test ne reçoit-il aucun verdict ?
Trois états ne font pas partie des 14, car aucun d'entre eux ne renseigne sur votre application : SKIPPED (le test n'a jamais été exécuté), INTERRUPTED (Ctrl+C, une limite --max-failures ou un délai d'expiration global l'a interrompu) et CONFIG_ERROR (le banc de test n'a pas pu le démarrer). Aucun d'entre eux ne crée de dossier de preuves ni de ligne dans l'Historique.
INTERRUPTED existe pour une raison concrète. Sans lui, un test interrompu basculait dans la branche de réussite et était consigné sous le statut SECURE : un verdict vert pour un test qui ne s'est jamais achevé.
Comment une réussite est-elle évaluée ?
- SECURE : réussi dès la première tentative, et aucune réparation n'a été nécessaire.
- AUTO_RECOVER : réussi, mais l'auto-réparation a dû remplacer un sélecteur dans ce test. Le localisateur rédigé par l'auteur est inopérant, et la prochaine modification de la page entraînera une rupture réelle de la suite ; une réussite réparée n'est donc jamais considérée comme irréprochable. Corrigez le sélecteur d'origine.
- FLAKY : échec, puis succès lors d'une nouvelle tentative, sans qu'aucune réparation n'ait été opérée. Quelque chose est instable, dans l'application ou dans le test, et rien n'a été corrigé.
Une exception : lorsque la première tentative a échoué uniquement en raison d'un dépassement de délai et que la nouvelle tentative a réussi, le verdict est SECURE. Cette réussite témoigne d'une latence, non d'une instabilité.
Comment un échec se voit-il attribuer un verdict ?
Lorsqu'un test échoue, le moteur analyse le message d'erreur et le journal réseau de l'exécution, puis les évalue par rapport à des groupes de modèles selon un ordre prédéfini. Le premier groupe correspondant détermine le verdict, cet ordre fait donc partie intégrante de la conception.
- CONFIG_ERROR en premier :
Cannot find module, uneReferenceErrorouSyntaxError, une variable d'environnement manquante, une fixture ayant échoué lors de l'initialisation. Si le banc de test n'a jamais démarré, tout symptôme ultérieur en découle. Les motifs sont délibérément stricts, limités aux erreurs que seuls le code de test ou son environnement peuvent générer : un CONFIG_ERROR de trop imputerait au banc d'essai un véritable bogue de votre application. - CRASHED :
Target closed,Page crashed, une erreur de protocole DevTools,SessionNotCreatedError, un identifiant de session invalide. Le navigateur ou le pilote a cessé de fonctionner. Il s'agit d'un problème d'infrastructure : vérifiez la machine et le pilote. - BLOCKED : un code 403 ou 429 dans l'erreur ou dans le journal réseau, un CAPTCHA, une page d'accès refusé ou un défi anti-bot que le moteur a détecté à l'écran. Le site s'est défendu et la requête n'a jamais atteint votre produit.
- UNREACHABLE : le réseau a opposé un refus avant même qu'une page ne soit observée : le nom n'a pas été résolu (
net::ERR_NAME_NOT_RESOLVEDsous Chromium,NS_ERROR_UNKNOWN_HOSTsous Firefox,Could not resolve hostnamesous WebKit), la connexion a été refusée ou la machine était hors ligne. Les erreurs de certificat n'entrent pas dans cette catégorie : il s'agit d'une anomalie constatée. - TIMEOUT :
Timeout 30000ms exceededde Playwright,Wait timed out afterde Selenium, uneTimeoutErrorou un test marqué comme expiré par Playwright. Une navigation dont le délai est dépassé correspond à un TIMEOUT, et non à UNREACHABLE : elle a bien démarré, mais la page était lente. - BREACHED_FLAKY : rien de ce qui précède ne l'explique, et le test avait déjà fait l'objet d'une nouvelle tentative. Il a échoué, et l'échec lui-même est incohérent. Comparez les tentatives avant de signaler un bogue.
- BREACHED : rien de ce qui précède ne l'explique, sur une seule tentative. Une assertion a échoué, et aucun modèle lié à l'environnement ou au banc de test n'explique l'erreur. C'est le rapport de bogue.
Chaque groupe prend en compte la formulation propre à Playwright ainsi qu'à Selenium WebDriver. Avant l'intégration des modèles Selenium, un TimeoutError de WebDriver et un SessionNotCreatedError dû à un chromedriver obsolète étaient tous deux signalés comme BREACHED, comme si l'application présentait un défaut.
Un véritable téléphone Android incapable d'exécuter le test parce qu'il s'est mis en veille ou est verrouillé est également classé BLOCKED : il s'agit d'un prérequis non satisfait, et non d'une défaillance du produit. Cette règle est issue d'un cas concret. Un téléphone s'est mis en veille au milieu d'une campagne, et un test de connexion qui avait réussi quatre fois de suite a été marqué d'un rouge critique.
Comment les exécutions de chaos sont-elles jugées ?
Lorsque l'exécution injecte des anomalies issues de Chaos Lab, le verdict répond à une autre question : l'application a-t-elle tenu bon ? Une réussite, SECURE ou AUTO_RECOVER, devient CHAOS_RESILIENT. Tout autre résultat devient CHAOS_BREACHED, y compris une réussite FLAKY et un TIMEOUT, car sous l'effet d'une anomalie injectée, ils en constituent l'impact. SKIPPED, INTERRUPTED et CONFIG_ERROR restent inchangés : un test qui n'a pas été exécuté ne dit rien de la résilience.
Quelles vérifications strictes peuvent modifier un succès ?
Trois vérifications s'exécutent parallèlement à vos assertions : les en-têtes de sécurité, l'accessibilité avec axe-core, ainsi que les budgets de performance pour les Web Vitals et le lazy loading. Elles enregistrent leurs observations à chaque exécution. Elles ne modifient le verdict que si vous les définissez comme strictes dans Settings. Sur une application existante, n'importe laquelle d'entre elles ferait passer toute la suite au rouge dès le premier jour, et une suite constamment au rouge est une suite que personne ne lit.
Lorsqu'elles sont strictes, elles ne s'appliquent qu'à un test réussi, dans l'ordre suivant : SECURITY_VIOLATION, A11Y_VIOLATION, PERFORMANCE_DEGRADED. La sécurité passe en premier car, des trois, c'est celle qui peut se solder par un incident plutôt que par une simple réclamation. Un test en échec n'est jamais requalifié à la hausse : BREACHED indique déjà un problème plus sérieux, et une mise en garde supplémentaire masquerait l'anomalie détectée.
Que voit la CI ?
Les sept verdicts de réussite renvoient le code de sortie 0 : SECURE, AUTO_RECOVER, FLAKY, CHAOS_RESILIENT, PERFORMANCE_DEGRADED, A11Y_VIOLATION et SECURITY_VIOLATION. Une réserve apparaît dans le rapport et dans History, et non sous la forme d'un build interrompu. Les sept autres renvoient le code 1. Les exécuteurs pytest et Selenium renvoient le code 2 lorsque l'exécution n'a pas pu démarrer du tout, par exemple en l'absence de Python ou avec un navigateur pour lequel le moteur ne dispose d'aucun pilote.
Quelles sont les limites de la méthode ?
- La classification analyse le texte de l'erreur. Un message que vous avez rédigé vous-même et qui contient
403,ForbiddenouAccess Deniedest interprété comme BLOCKED, et une erreur contenantis not a functionest lue comme CONFIG_ERROR. Veillez à ce que vos messages d'assertion personnalisés soient précis, et consultez metadata.json lorsqu'un verdict vous surprend. - Un TIMEOUT ne constitue pas la preuve que l'application fonctionne. Il indique simplement que l'exécution ne peut pas se prononcer. Un test qui expire à chaque exécution mérite que l'on s'y intéresse.
- Les tentatives de rejeu (« retries ») séparent FLAKY de SECURE, et BREACHED_FLAKY de BREACHED. Sans ces tentatives, un échec intermittent est considéré comme un BREACHED.
- Les tests d'API disposent de sept verdicts qui leur sont propres, régis par d'autres règles : voir les tests d'API.
Où puis-je voir un verdict sur un échec réel ?
La page Preuves suit un test en échec et répertorie chaque fichier que chaque verdict dépose sur votre disque : report.md, metadata.json, raw-data.json, une capture d'écran et, pour un véritable échec, la vidéo. L'essai de 30 jours exécute le même moteur sur vos propres tests.