不稳定测试不是“偶尔红一下”,而是对信号的持续破坏。这篇用三种真实的不稳定来源、重试对失败信号的掩盖,以及基于标签的隔离,量出它们各自的失败率与治理手段的真实代价。
(校准:3000 万次计算最快 51.5 ms,取 8735828 次约 15 ms)
类型 1 并发(两个线程同时第一次创建单例,检查再创建,没有同步):
空闲:race 4000 次,失败 385 次(9.63%),用时 302 ms
满载(30 个空转进程):race 4000 次,失败 18 次(0.45%),用时 480 ms
-XX:ActiveProcessorCount=1:race 4000 次,失败 171 次(4.28%),用时 320 ms
类型 2 时序(断言“一个约 15 ms 的计算在 40 ms 内完成”):
空闲:timing 300 次,失败 0 次(0.00%),用时 4536 ms
满载(30 个空转进程):timing 300 次,失败 218 次(72.67%),用时 16656 ms
类型 3 顺序(共享静态状态,随机顺序;与负载无关):
空闲:order 4000 次,失败 646 次(16.15%),用时 16 ms
满载(30 个空转进程):order 4000 次,失败 646 次(16.15%),用时 33 msretry 2000 次测试运行(每次最多 3 次尝试):第 1 次就通过 1833,第 2 次通过 154,第 3 次通过 12,3 次都失败 1;第一次尝试失败的有 167 次(被重试“治好”的有 166 次)
[全部运行] 退出码 1
EV alwaysFails 被调用
EV alwaysFails 被调用
EV alwaysFails 被调用
EV flakyUntilThird 第 1 次调用
EV flakyUntilThird 第 2 次调用
EV flakyUntilThird 第 3 次调用
│ └─ Suite ✔
│ ├─ quarantinedOk() ✔
│ ├─ alwaysFails() ✔
│ │ ├─ 尝试 1/3 ■ 第 1 次尝试失败,重试:真的有 bug,总是失败
│ │ ├─ 尝试 2/3 ■ 第 2 次尝试失败,重试:真的有 bug,总是失败
│ │ └─ 尝试 3/3 ✘ 真的有 bug,总是失败
│ ├─ stable() ✔
│ ├─ quarantinedFlaky() ✘ 已隔离的不稳定测试
│ ├─ realBug() ✘ 没有被隔离的真实失败
│ └─ flakyUntilThird() ✔
│ ├─ 尝试 1/3 ■ 第 1 次尝试失败,重试:前两次失败 ==> expected: <true> but was: <false>
│ ├─ 尝试 2/3 ■ 第 2 次尝试失败,重试:前两次失败 ==> expected: <true> but was: <false>
│ └─ 尝试 3/3 ✔
→ 10 tests found | 0 tests skipped | 4 tests aborted | 3 tests successful | 3 tests failed [门禁任务:--exclude-tag quarantine] 退出码 1
EV alwaysFails 被调用
EV alwaysFails 被调用
EV alwaysFails 被调用
EV flakyUntilThird 第 1 次调用
EV flakyUntilThird 第 2 次调用
EV flakyUntilThird 第 3 次调用
│ └─ Suite ✔
│ ├─ alwaysFails() ✔
│ │ ├─ 尝试 1/3 ■ 第 1 次尝试失败,重试:真的有 bug,总是失败
│ │ ├─ 尝试 2/3 ■ 第 2 次尝试失败,重试:真的有 bug,总是失败
│ │ └─ 尝试 3/3 ✘ 真的有 bug,总是失败
│ ├─ stable() ✔
│ ├─ realBug() ✘ 没有被隔离的真实失败
│ └─ flakyUntilThird() ✔
│ ├─ 尝试 1/3 ■ 第 1 次尝试失败,重试:前两次失败 ==> expected: <true> but was: <false>
│ ├─ 尝试 2/3 ■ 第 2 次尝试失败,重试:前两次失败 ==> expected: <true> but was: <false>
│ └─ 尝试 3/3 ✔
→ 8 tests found | 0 tests skipped | 4 tests aborted | 2 tests successful | 2 tests failed
[隔离任务:--include-tag quarantine] 退出码 1
│ └─ Suite ✔
│ ├─ quarantinedOk() ✔
│ └─ quarantinedFlaky() ✘ 已隔离的不稳定测试
→ 2 tests found | 0 tests skipped | 0 tests aborted | 1 tests successful | 1 tests failed