仅有通过或失败还不够:14 种判定结果是如何确定的
测试标红本应意味着应用程序出了问题。如果标红也可能只是 DNS 短暂故障、网站弹出人机验证码或浏览器崩溃,团队就会习惯于重跑标红的测试,而不是查看结果,真正的缺陷也就淹没在噪声中。Nexus Studio 为每次运行给出 14 种判定结果之一,而非只有两种。本页将按引擎的决策顺序,说明它如何作出判定,以及这种方法有哪些局限。
作者:Verdict System LLC 的 Nexus Studio 团队。2026 年 10 月 7 日。
14 种判定结果有哪些?
这 14 种判定结果是 SECURE、CHAOS_RESILIENT、AUTO_RECOVER、FLAKY、PERFORMANCE_DEGRADED、A11Y_VIOLATION、SECURITY_VIOLATION、BREACHED、BREACHED_FLAKY、CHAOS_BREACHED、TIMEOUT、UNREACHABLE、BLOCKED 和 CRASHED. 它们分为四组:通过、有保留地通过、应用出现故障,以及因环境或测试框架有问题而无法对应用作出判定。
引擎如何作出判定?
引擎会按以下顺序询问三个问题:
- 测试到底有没有产生结果?
- 如果通过了,是否毫无隐患?
- 如果失败了,问题出在测试框架、环境,还是应用程序?
只有一种结果应当作为缺陷报告:归因于应用程序的失败。其他结果反映的都是别的问题,因此会用相应的名称明确标示。
什么情况下测试完全不作判定?
有三种状态不在这 14 种判定结果之中,因为它们都不能说明应用程序的情况: SKIPPED (测试从未运行)、INTERRUPTED (Ctrl+C、--max-failures 阈值或全局超时终止了测试) 和 CONFIG_ERROR (测试框架无法启动测试). 它们都不会生成证据文件夹或历史记录行。
引入 INTERRUPTED 有一个具体原因。没有它时,被中止的测试会落入通过分支,并被记录为 SECURE: 一个从未完成的测试,却得到了绿色判定。
测试通过后如何分级?
- SECURE: 首次尝试即通过,且未进行任何修复。
- AUTO_RECOVER: 测试通过,但自愈机制不得不替换该测试中的一个选择器。作者编写的定位器已经失效,页面下次变动就会让测试套件真正失效,因此自愈后通过的测试绝不会被报告为毫无隐患。请修复原始选择器。
- FLAKY: 首次失败,随后重试通过,且未进行任何自愈。应用程序或测试中存在不稳定因素,而问题并未得到修复。
有一种例外:如果首次尝试仅因超时而失败,随后重试通过,判定结果为 SECURE. 这种通过说明存在延迟,而非不稳定。
测试失败后如何确定判定结果?
测试失败时,引擎会读取本次运行的错误消息和网络日志,并按固定顺序与各组模式进行匹配。首个匹配的模式组决定判定结果,因此匹配顺序也是设计的一部分。
- 首先是 CONFIG_ERROR:
Cannot find module、ReferenceError或SyntaxError、缺少环境变量、测试夹具在初始化时失败。如果测试框架根本没有启动,之后的任何症状都是由此导致的。这些模式刻意限定在很小的范围内,只涵盖测试代码或其环境才会产生的错误:哪怕多误判一次 CONFIG_ERROR, 都可能把应用程序中的真实缺陷归咎于测试框架。 - CRASHED:
Target closed、Page crashed、DevTools 协议错误、SessionNotCreatedError、无效的会话标识符。浏览器或驱动程序崩溃了。这是基础设施问题:请检查机器和驱动程序。 - BLOCKED: 错误或网络日志中出现 403 或 429、人机验证码、拒绝访问页面,或引擎在屏幕上识别到的反机器人验证。网站启动了防御机制,请求根本没有到达你的产品。
- UNREACHABLE: 尚未观察到任何页面,网络就已拒绝请求:域名无法解析 (Chromium 中的
net::ERR_NAME_NOT_RESOLVED、Firefox 中的NS_ERROR_UNKNOWN_HOST、WebKit 中的Could not resolve hostname)、连接被拒绝,或机器处于离线状态。证书错误不属于此类:那是检测出的问题。 - TIMEOUT: Playwright 的
Timeout 30000ms exceeded、Selenium 的Wait timed out after、TimeoutError, 或被 Playwright 标记为超时的测试。页面导航超时属于 TIMEOUT, 而非 UNREACHABLE: 导航已开始,只是页面响应缓慢。 - BREACHED_FLAKY: 上述情况均无法解释此次失败,且测试已经重试过。测试失败了,而失败本身也不一致。提交缺陷报告前,请先比较各次尝试。
- BREACHED: 仅尝试一次,且上述情况均无法解释此次失败。某个断言失败了,且没有任何环境或测试框架模式能够解释该错误。这就是应当提交的缺陷报告。
每组都涵盖 Playwright 和 Selenium WebDriver 的错误表述。在引入 Selenium 匹配模式之前,WebDriver 的 TimeoutError 和过时的 chromedriver 引发的 SessionNotCreatedError 都会被报告为 BREACHED, 仿佛应用存在缺陷。
真实 Android 手机如果因进入休眠或被锁定而无法执行测试,也会被判为 BLOCKED: 这是前提条件未满足,而非产品故障。这条规则源于一个实测案例。一部手机在一轮测试进行到一半时进入休眠,导致一个连续通过四次的登录测试被标红为严重故障。
如何评判混沌测试运行?
当测试运行注入 Chaos Lab 的故障时,判定回答的是另一个问题:应用是否经受住了考验?通过判定 SECURE 或 AUTO_RECOVER 会变为 CHAOS_RESILIENT. 其他结果一律变为 CHAOS_BREACHED, 包括 FLAKY 通过和 TIMEOUT, 因为在注入故障的情况下,这些结果就是故障造成的影响。SKIPPED, INTERRUPTED 和 CONFIG_ERROR 保持不变:未执行的测试无法说明应用的韧性。
哪些严格检查会改变通过结果?
除了断言,还会执行三项检查:安全响应头,使用 axe-core 进行的无障碍检查,以及针对 Web Vitals 和延迟加载的性能预算检查。每次运行都会记录检查发现的问题。只有在设置中将其设为严格模式时,它们才会改变判定。对于现有应用,其中任何一项都可能在第一天就让整个测试套件标红,而始终标红的测试套件最终会无人问津。
在严格模式下,这些检查仅适用于已通过的测试,并按以下顺序生效: SECURITY_VIOLATION, A11Y_VIOLATION, PERFORMANCE_DEGRADED. 安全检查优先,因为这三项中,安全问题可能引发事故,而不只是招来投诉。已失败的测试绝不会进一步升级判定:BREACHED 已经表明了更严重的问题,额外叠加提示反而会掩盖这一发现。
CI 会看到什么?
七种通过判定的退出码为 0: SECURE, AUTO_RECOVER, FLAKY, CHAOS_RESILIENT, PERFORMANCE_DEGRADED, A11Y_VIOLATION 和 SECURITY_VIOLATION. 保留意见会显示在报告和历史记录中,而不会导致构建失败。其余七种判定的退出码为 1. 如果运行根本无法启动,例如未安装 Python, 或引擎没有对应浏览器的驱动程序,pytest 和 Selenium 运行器的退出码为 2.
这种方法有哪些局限?
- 分类依据是错误文本。如果你自己编写的消息包含
403,Forbidden或Access Denied, 就会被判为 BLOCKED, 而包含is not a function的错误会被判为 CONFIG_ERROR. 自定义断言消息应具体明确,如果判定出乎意料,请打开 metadata.json 查看。 - TIMEOUT 并不能证明应用运行正常。它表示本次运行无法得出结论。如果某项测试每次运行都超时,就值得检查一下。
- 重试是区分 FLAKY 与 SECURE, 以及 BREACHED_FLAKY 与 BREACHED 的依据。关闭重试后,间歇性失败会被判为 BREACHED.
- API 测试有七种独立判定,由另一套规则决定:请参阅 API 测试.
在哪里可以看到真实故障的判定结果?
证据页面以一个失败的测试为例,列出每种判定会在磁盘上留下的所有文件:report.md, metadata.json, raw-data.json, 截图,以及真正失败时的视频。 30 天试用版可使用同一引擎运行你自己的测试。