如何区分真正的缺陷和不稳定的测试?
关闭重试,多次运行测试并统计结果。真正的缺陷每次运行都会以同样的方式导致失败,而不稳定的测试在没有任何改动的情况下,有时通过,有时失败。下面的示例可以在任何安装了 Playwright 的机器上执行这一操作,随后介绍 Nexus Studio 如何处理每种结果。
由 Verdict System LLC 的 Nexus Studio 团队撰写。2026年10月27日。
如何在一分钟内区分两者?
关闭重试,连续多次运行测试。Playwright 通过两个参数实现这一点: --retries=0 禁用重试,防止重试掩盖失败,而 --repeat-each=6 会将每个测试运行六次。然后统计每个测试的结果。
- 每次都失败: 在有证据证明并非如此之前,先按缺陷处理。每次运行都失败也可能是环境导致的,例如请求被阻止或主机无法访问,所以要先查看错误信息。
- 有时通过,有时失败: 这是不稳定的测试。这些运行之间,代码和测试都没有变化,因此应用或测试中存在某种不稳定因素。
- 每次都通过: 暂时没有发现问题。如果缺陷每五十次运行才出现一次,就需要增加运行次数,或查看该测试的历史记录。
有可以运行的示例让我试试吗?
将以下内容保存为 bug-or-flaky.spec.js. 第一个测试模拟不稳定的情况:每运行三次就有一次失败。第二个测试是真正的缺陷:页面显示 "Welcome", 而测试期望的是 "Welcome back", 所以每次运行都不可能通过。
import { test, expect } from '@playwright/test';
// Fails on its first attempt of every third run, passes otherwise: a simulated flake.
test('flaky: a slow load now and then', async ({ page }, info) => {
await page.setContent('<h1>Welcome</h1>');
expect((info.repeatEachIndex + info.retry) % 3, 'simulated slow load').not.toBe(0);
});
// Fails the same way every time: the heading says "Welcome", the test expects "Welcome back".
test('real bug: wrong heading', async ({ page }) => {
await page.setContent('<h1>Welcome</h1>');
await expect(page.locator('h1')).toHaveText('Welcome back', { timeout: 300 });
});
关闭重试,运行六次:
npx playwright test --retries=0 --repeat-each=6
Playwright 最终显示 8 次失败,4 次通过。要回答这个问题,关键是看每个测试各自的统计结果,list 报告器已逐行输出这些结果:
flaky: a slow load now and then 4 passed, 2 failed
real bug: wrong heading 0 passed, 6 failed
现在运行一次,允许重试两次:
npx playwright test --retries=2
Playwright 最终在每个分组中各显示一个测试。不稳定的测试首次尝试失败,第 #1 次重试通过。真正的缺陷在三次尝试中全部失败。
1 failed
bug-or-flaky.spec.js:10:1 › real bug: wrong heading
1 flaky
bug-or-flaky.spec.js:4:1 › flaky: a slow load now and then
重试通过就意味着应用没问题吗?
不是。重试通过只能说明各次尝试的结果不一致,仅此而已。如果运行结果变绿后就无人查看,应用中的间歇性缺陷就会被掩盖,例如竞态条件,共享数据或响应缓慢的依赖项所导致的问题,而这些恰恰是排查成本最高的缺陷之一。应将不稳定的结果视为发现了问题,而不是可以忽略的通过结果,也不要认定问题一定出在测试中。
Nexus Studio 如何处理每种结果?
Nexus Studio 会记录每次尝试,并为结果给出独立判定,因此重试绝不会把缺陷变成单纯的绿色通过结果。
- FLAKY: 测试失败后重试通过,但并未修复任何问题。退出码为 0, 因此不会导致构建失败,报告和历史记录中则会注明这一保留意见。
- BREACHED: 测试仅尝试一次便失败,且没有任何环境或测试框架的已知问题模式可以解释该错误。退出码为 1.
- BREACHED_FLAKY: 测试经过重试后,在最后一次尝试中仍然失败,且没有任何已知环境问题模式可以解释。退出码为 1. 提交缺陷前,请对比各次尝试。
历史记录会为每个测试的每次运行保留一行记录,因此测试从绿变红再变绿的过程会呈现为趋势,而不是淹没在重新运行的结果中。 不稳定测试指南列出了每种判定会留下的文件。
有哪些局限?
- 示例通过算术运算模拟测试不稳定的情况,以便重复出现。实际的测试不稳定都有原因,而查明原因仍需要人工完成。
- 运行六次只是快速筛查,并非统计分析。每五十次运行才出现一次的失败,可能连续六次都不出现。
- 每次运行都失败,不一定是应用存在缺陷:网络缓慢,拦截页面或浏览器崩溃也会导致测试失败。 误报失败指南介绍了如何区分。
- 关闭重试后,Nexus Studio 会将间歇性失败判定为 BREACHED,因为只有重试才能区分 FLAKY 和普通失败。分类依据是错误文本,所以当判定结果出乎意料时,请打开 metadata.json 查看。
在哪里可以看到?
判定指南解释了引擎确定全部 14 种判定结果的顺序,证据页面则追踪一个失败测试留下的每个文件。30 天试用版可使用同一引擎运行您自己的测试。