Skip to content

Commit 547541c

Browse files
os-zhuangclaude
andauthored
docs(agents): record the flaky-test discipline learned in #3010 (#3015)
#3010 fixed five load-sensitive flaky tests that all shared one root cause — an unbounded module load billed against a bounded window — and found one file that had already been "fixed" once by raising its timeout to 15s (and still blew it at 15021ms under full load). Without writing the rule down, the next agent reaches for the same band-aid. Adds a `测试纪律` subsection to §9 covering: assert-behind-a-lazy-boundary -> import at module scope (the import phase has no test/hook timeout); why `beforeAll` is the wrong warm-up spot (`hookTimeout` 10s is *narrower* than `testTimeout` 15s); that raising a timeout or adding a file to `heavyDomTests` is forbidden as a flake fix; how to read the two tells (a Suspense fallback in the dump, and a failed *file* with 0 failed *tests*); and the stale-install trap that makes a wall of local parity failures look like a regression. Docs only — no code, no changeset. Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent a045a32 commit 547541c

1 file changed

Lines changed: 13 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,19 @@ export const SchemaRenderer = ({ schema }: { schema: UIComponent }) => {
149149
- 任务结束:停**自己起的**后台服务(见下方"服务纪律";别按端口杀别人的)、清 `.playwright-mcp/`
150150
- 改完代码提交时:功能改进(feature)需写 changeset(`pnpm changeset`);纯 bug 修复不需要。
151151

152+
### 测试纪律(flaky 测试:先找竞态,别调超时)
153+
154+
单跑稳定绿、全量并行下偶发红的测试,**根因几乎总是同一个**:一段**无界的模块加载被计入了一个有界的窗口**。满并行下 Vite 的 transform 管线是饱和的(单 `dom-heavy` 项目就 ~60s transform),实测一次首包 `import()` 可达 **976ms** —— 已吃掉 RTL `findBy`/`waitFor` 默认 **1000ms** 预算的 97.6%。于是断言在和模块加载器抢时间,红绿取决于机器负载而不是被测代码。
155+
156+
- **断言的内容落在 `React.lazy` / 动态 `import()` 边界之后 → 在测试文件的模块作用域直接 `import` 该模块**(`import '@object-ui/plugin-charts';` + 一行注释说明原因)。成本进入 import 阶段,**不受任何 test/hook 超时约束**。specifier 必须与被测组件里的**完全一致** —— ESM 按解析后的 specifier 缓存,这样组件自己的 `React.lazy` 工厂才会立刻 resolve。
157+
- **不要用 `beforeAll` 预热**:它受 `hookTimeout`(**10s**)约束,比它取代的 `testTimeout`(**15s**)**更窄**,那只是把问题挪个窝。
158+
- **禁止**用「调高超时」或「把文件塞进 `vitest.config.mts``heavyDomTests`」来修 flaky —— 两者都只是把竞态藏起来。`heavyDomTests` 只用于 registry「`<type>` not registered」这类失败。
159+
- 失败现场会直接指认根因:dump 里若仍是 Suspense fallback(如 `Loading report renderer…`),就是本条;**hook 超时表现为「失败的*文件* + 0 个失败*测试***(其余全部 skipped),别误读成断言失败。
160+
- 顺手体检:别把 `keysOf(x)` 这类整体计算写在 `.filter()` 谓词里(每个元素重算一遍)。`all-locales-key-parity` 曾因此 7.51s,提升出谓词后 **25ms**
161+
- **本地一片 parity/schema 测试失败,先怀疑 stale install**(`node_modules` 里的 `@objectstack/spec` 版本落后于 lockfile),不是回归 —— CI 每次全新安装,永远不会命中这个。
162+
163+
前情:objectui#3010(一次修掉五个文件,含一个已被「超时调到 15s」糊过、满负载下依然 15021ms 超时的例子)。
164+
152165
### 版本号策略(version alignment)
153166
- **objectui 的 major 与 `@objectstack`(spec/client/formula)的 major 保持一致**:依赖到 `@objectstack ^11.x` 时,objectui 这个固定版本组(`.changeset/config.json``fixed`,39 个包一起发)的 major 必须是 `11`。心智模型:**major 相同即兼容**
154167
- minor/patch **独立演进**——objectstack 没动时不必跟发;objectui 自己的改动照常用 changeset 推进(从当前 major 起步,如 `11.0.0 → 11.1.0`)。

0 commit comments

Comments
 (0)