新写的退款测试很长,只检查一个状态。但在检查之前,它先手工建了个内存数据库,手工跑迁移,再手工创建用户和订单。这个形状你熟——就是那个好几年没人清理的老订单测试文件。Agent 读了它,然后照着做了。
Simon Willison 今年两次提到这件事。1 月 26 日的一篇帖子源自他本人在 Hacker News 的回复,他写道:“Coding agents pick the existing patterns up without needing any extra prompting at all.” 他补充说,一旦项目有了干净的基础测试,“the new tests added by the agents tend to match them in quality.”
反过来读这句话。如果 Agent 复制的是你现有的测试,那么你最难看的那个测试文件,就出现在你发出的每一条测试提示里——不管你有没有这个意图。
所以我的看法是:花一小时清理你最烂的三个测试文件,对 Agent 产出的影响,比在 CLAUDE.md 里再写一段话更大。我没见过这方面的基准测试,自己也没跑过。这个论点建立在 Willison 的报告和各家 Agent 厂商文档里“别往指令文件里塞什么”的说法上。
Willison 到底说了什么
1 月那篇帖子很短,也很实用。在他看来,让 Agent 写出好测试的最佳路径,是一个已经有良好模式测试套件的项目。当他想要某种特定测试风格时,会让 Agent 克隆另一个项目去模仿,因为“the quickest way to show an agent how you like something to be done is to have it look at an example.”
他也点名了你最可能继承的那个失败模式:“The most common anti-pattern I see is large amounts of duplicated test setup code.” 他说自己对测试里重复的容忍度高于实现代码,但仍然会用两条提示去纠正:“Refactor those tests to use pytest.mark.parametrize” 和 “extract the common setup into a pytest fixture.”
他在旧金山 Pragmatic Summit 上又回到这个话题,那是 2 月的一场炉边谈话,他 3 月 14 日写了出来。“If you've got a codebase with a bunch of patterns in, they will follow those patterns almost to a tee.” 还有一句应该让你好受点的话:“Even having just one or two tests in the style that you like means it'll write tests in the style that you like.”
所以计划很小:放几个好例子,放在 Agent 最先找到的地方。
你的 CLAUDE.md 在跟测试文件夹抢注意力
看看 Anthropic 让你往 CLAUDE.md 里放什么。它的最佳实践页面有一张“该省略什么”的表,第一行就是“Anything Claude can figure out by reading code.” 同一页还说要把 Claude 指向代码库里的模式,示例提示里点名某个文件是“a good example”,并说“follow the pattern.”
记忆文档说得更远。Claude 把 CLAUDE.md “as context, not enforced configuration.” 目标是每个文件控制在 200 行以内,因为“longer files consume more context and reduce adherence.” Codex 在“before doing any work”之前读 AGENTS.md,指令文件默认累计到 32 KiB 就不再追加。
厂商的预期是:你的约定活在代码里,指令文件保持简短。现在设想一条规则“use the shared fixtures in conftest.py”,写在一个大多数测试文件都内联建数据库的仓库里。规则只是一行建议性上下文。反例则是 Agent 干活时读到的整个文件。我的解读是,文件赢的次数比你想的多。这是观点,不是测量,但它和 Willison 描述的一致:模式被拾取“without needing any extra prompting at all”,包括坏模式。
一小时的清理
挑三个范本。选 Agent 最常碰的区域里的测试文件。好的范本一个测试只测一个行为,名字读起来像句子,setup 来自 fixture,不碰网络也不 sleep。
把重复的 setup 抽进 fixture。这就是 Willison 称为最常见反模式的那种形状。下面用 app 代指你自己的代码:
- 清理前:每个测试函数开头都是四行——建内存库、跑迁移、加用户、加订单,然后才断言。
- 清理后:把 db 和 user 抽成 conftest.py 里的 fixture,测试体只剩两行 arrange-and-assert。
pytest 文档说,定义在 conftest.py 里的 fixture “can be used by any test in that package without needing to import them”。同样的动作在 Python 之外也成立:Jest 或 Vitest 里的共享 factory 或 beforeEach,干的就是 conftest.py 在这里干的活。
把只有一个行为、多个输入的用例参数化。上面两个测试只差订单状态和预期结果,这正是 pytest.mark.parametrize 的用途。改完之后,Agent 复制的例子就是两行 arrange-and-assert,setup 只活在一个地方。
把 Agent 指向好的那些
清理文件提高了 Agent 复制对东西的概率。点名则消除了猜测。在 Claude Code 里,路径作用域的规则只在 Claude 读、写或编辑匹配文件时加载,所以从不碰测试的会话里它零成本。把规则存成 .claude/rules/testing.md,内容就三条:新测试模仿 tests/test_refunds.py 和 tests/test_invoices.py;共享 setup 放在 tests/conftest.py,在那里加 fixture 而不是内联重建;同一行为多个输入就用 parametrize。
对 Codex 和其他读 AGENTS.md 的 Agent,把同样三行放进一个简短的“Tests”标题下。它很短,远在体积上限之内。
然后在任务本身里说出来,就像 Anthropic 自己的示例提示那样:“Write tests for refund() in the style of tests/test_refunds.py, using the fixtures in tests/conftest.py.” 如果结果还是内联 setup,就在 review 时用 Willison 那两条纠正提示,合并前先重构 Agent 写的测试。你合并的每一个测试,都是下一个 Agent 的范例。
Hermes 的扫描只能报告你代码里有的东西
我自己在做 Hermes IDE,所以这一节请带着这个前提看。Hermes 让 Claude Code、Codex 和其他 CLI Agent 并排跑,各自一个终端。它的项目扫描会识别每个项目的语言、框架、架构和约定,并把发现的东西指给 Agent 看,放在一个你可以按项目设置的 token 预算内的上下文文件里。你也可以把文件钉到项目上,被钉的文件“reach every later session's agent, also after a restart.” 把你那三个范本测试钉住,是确保每个会话都看到它们的直接办法。
扫描读的是你的代码库。如果你的测试没有共享 fixture、没有一致的形状,就没有约定可找,上下文文件也报不出来。先清理那三个文件,再让扫描和钉住把它们带下去。Hermes 免费,源码在 BSL 1.1 下可见,跑在 macOS、Windows 和 Linux 上;2.3.4 于 2026 年 10 月 15 日发布。它与 Nous Research、Anthropic、OpenAI 或任何 Agent 厂商都没有关联。
这个看法最弱的地方
它建立在一位有经验的实践者的观察和厂商指引上,不是对照研究。Willison 的例子是 pytest,我也没有测量过某个具体 Agent 在测试文件和指令文件之间如何分配权重。
指令文件仍然重要。Anthropic 同一张表也告诉你,CLAUDE.md 里要留那些代码展示不了的东西:Claude 猜不到的命令、测试说明、环境怪癖。别删掉你的。别再用它去描述一个跟你测试文件夹相矛盾的测试风格。
一个庞大的遗留测试套件也不可能一小时修好。所以这个动作是三个范本加一个指针,不是重写。套件剩下的部分会以它变坏的方式变好:一次一个被复制的测试。
热门跟贴