让 GPT-5.5 或 Claude Sonnet 4.6”写测试”,你拿到的往往是撑覆盖率的代码:断言逐行镜像实现,代码改坏了它照样过。下面这 13 个 Prompt 强制让 AI 写基于行为的测试,并针对 2026 年中团队真正在用的框架做了调校:Vitest 3、Jest 30、pytest 9、Playwright。
一句话总结
- AI 生成测试的默认翻车方式是 change-detector 测试:它重新断言代码”现在长什么样”,于是每次重构都失败,却抓不到任何真 bug。下面每个 Prompt 都改成钉死行为契约。
- 声明框架和版本。Vitest 3 与 Jest 30 大约 95% API 兼容,但 mock 和配置差得足以让混语法文件跑不起来。
- 把模型当草稿作者,不是终稿作者。生成后改一行被测代码再跑;如果所有测试还过,说明这些测试是噪声。
- 单元测试单独看姊妹篇 单元测试生成 Prompt。本篇讲集成、E2E、API、组件、快照和套件健康度。
适合哪些人
重构前要补安全网的工程师、要让 PR 过覆盖率门槛的贡献者、上线前想要底气的独立开发者,以及接手了一堆没有测试代码的人。
什么时候别用这些 Prompt
不打算保留的代码别写测试,先写规格。一次性脚本、琐碎的 getter/setter 也别写,测试成本远超它能抓的 bug。也不要让模型把测试直接自动合进 CI:一个”绿但没意义”的套件比没有套件更糟,因为它会骗团队说重构是安全的,其实并不安全。
Prompt 结构:六个要素
测试生成 Prompt 永远要带这六样。少一样,模型就用猜测填空。
| 要素 | 要写明的 | 为什么重要 |
|---|---|---|
| 被测对象 | 函数 / 模块 / endpoint,附签名与类型 | 没类型模型就乱编输入 |
| 测试分类 | unit / integration / e2e / property——别说”写点测试” | 决定工具和隔离级别 |
| 行为契约 | 代码”必须做什么”,不是”现在怎么写的” | 防 change-detector 测试 |
| 覆盖范围 | happy path + N 个边界 + 1 个非法输入 | 明确数量强迫完整 |
| 框架与风格 | vitest、pytest、go test,附 mock vs 真实规则 | 阻止 Jest/Mocha 语法混用 |
| 输出形态 | 只要可运行代码,除非要求否则不夹散文 | 让答案可直接粘贴 |
先选对框架
告诉模型框架和大版本。到 2026 年这些 runner 差异已经够大,对着 Vitest 项目说”写 Jest 测试”会得到一个跑不起来的文件。
| 框架 | 团队在用的版本(2026 年中) | 最适合 | 必须告诉 AI 的一点 |
|---|---|---|---|
| Vitest | 3.x 仍广泛使用(当前已是 4.x) | Vite / TypeScript 应用,browser mode 走 Playwright | 用 vi.mock,不是 jest.mock;默认 ESM |
| Jest | 30(2025 年 6 月发布) | 老 CommonJS、React Native、大型 monorepo | 确认 ESM 还是 CJS;React Native 不支持 Vitest |
| pytest | 9.0.x(9.0 于 2025 年 11 月发布) | Python 服务与库 | 优先 fixture 而非 setup/teardown;表格用 parametrize |
| Playwright | pytest-playwright 0.8.0 / @playwright/test | 浏览器 E2E、跨浏览器 | 断言用户可见状态,自动等待,不要 sleep() |
13 个可直接复制的 Prompt 模板
发送前把每个 [方括号] 占位符换成你的具体内容。
1. 基于行为的单测
为 [function] 按可观察行为写单测,不测内部状态。
覆盖:happy path、3 个 edge case、1 个非法输入。用 [测试框架]。
做保持行为的重构后,这些测试仍应通过。
2. 从 bug 报告写回归测试
Bug:[描述]。复现:[步骤]。
写 1 个最小失败测试捕获它。
它必须在 main(修复前)失败、在我的分支(修复后)通过。
3. 性质测试想法
为 [function] 识别 3 个应永远成立的性质
(如"无论输入顺序,输出有序")。
用 [fast-check / Hypothesis] 写性质测试桩。
4. 边界输入测试
为 [带类型的 function] 生成边界测试:
空、单、最大、超长、特殊字符、unicode、负数。
标出当前哪些会失败。
5. 流程集成测试
下面是涉及 [N 个组件] 的流程。
写 3 个集成测试:golden path、每步注入 1 个失败、恢复。
[粘贴流程]
6. Mock vs 真实
为 [feature] 建议哪些依赖该 mock、哪些保真。
每个选择按稳定性 vs 速度的权衡说明理由。
7. 快照测试审视
下面是现有快照测试。每个判断:有用,还是噪声?
对任何只为检测变化而存在的快照,给出一条有针对性的断言来替换它。
[粘贴]
8. flaky 测试诊断
测试 [name] flaky。可能原因按优先级排序:
网络、时序、共享状态、随机性、顺序。
读测试和被测代码,指出最可能原因和修法。
[粘贴]
9. API endpoint 测试
为 endpoint `[METHOD /path]`(handler 见下),用 [framework] 写集成测试,覆盖:
(1) 带有效鉴权的 happy path,(2) 401 未授权,(3) 403 角色错误,
(4) 400 非法 body——指明具体哪个字段非法,
(5) 404 资源不存在,(6) 重试下的幂等(同一 key 第二次调用)。
每个用例必须自行 seed 和清理 DB 状态。
[粘贴 handler + schema]
可替换变量: framework(supertest + Vitest、pytest + httpx 等)
优化建议: 若有 OpenAPI 或 Zod schema 也一起贴,模型会从 schema 自动派生非法输入用例。
10. React / UI 组件测试
为下面的 React 组件用 [framework,如 RTL + Vitest] 写测试。
覆盖:(1) 给一组典型 prop 能渲染,(2) 用户交互时调用正确回调,
(3) 处理 loading 状态,(4) 处理 error 状态,
(5) 无障碍——可聚焦、有 label、role 正确。
用 role 和 label 查询,不要用 test id 或组件内部细节。
[粘贴组件]
11. 测试金字塔平衡
测试套件臃肿却无效时跑这个。
下面是我的测试目录结构和测试文件列表。
分析测试金字塔:unit / integration / e2e 的比例。
找出 (1) 金字塔倒置的地方(e2e 太多),
(2) 应该下推的测试(e2e 到 integration 到 unit),
(3) 层与层之间的重复覆盖,
(4) 5 个能在不损失安全性的前提下把 CI 时间砍掉至少 30% 的具体调整。
[粘贴目录树 + 示例测试]
12. 无工具找覆盖缺口
不要跑覆盖率工具。下面是被测模块和它当前的测试文件。
定性地找出:(1) 3 个完全没覆盖的分支,
(2) 任何没被触达的错误路径,
(3) 任何生产里用到但测试里没有的数据形态,
(4) 我这周该补的 5 个最高 ROI 测试,
按 出 bug 概率 × 用户影响 排序。
模块:[粘贴]
测试:[粘贴]
13. 测试命名与结构清理
下面是我 20 个测试的名字和函数体。重写得更易读:
(1) 命名格式"单元 / 场景 / 预期结果",
(2) 去掉无信息量的"tests""should"前缀,
(3) 把重复的 setup 收进 beforeEach(或 pytest fixture),
(4) 标出任何 2 个测的是同一件事的测试并建议合并。
[粘贴测试]
在 agent 里生成测试(Claude Code / Cursor)
当模型能读你的仓库时,效果比复制粘贴好得多。让它匹配你已有的风格,而不是自己另造一套。
- 先指给它一个邻近测试文件:“读
[path/to/example.test.ts],然后用同样风格为[目标]写测试。“贴片段式生成的测试在 PR 评审里很违和。 - 让它生成后跑一遍套件,并报告具体失败的断言,而不是默默把它们改掉。
- 在独立分支上做。自动合入的坏测试会污染整个团队的 CI。
- 它写完后,你自己改一行被测代码再跑。套件如果还是绿的,把缺口用模板 12 再扔回去。
Claude Code 只跑 Anthropic 模型(Sonnet 4.6 是主力,最难的推理用 Opus 4.7)。Cursor 可以把同一活儿路由给 Sonnet 4.6、GPT-5.5 或 Gemini 3.1 Pro,想用第二个模型来复核第一个的断言时很有用。如果 agent 悄悄丢掉了一个红色测试,参见 Claude Code 为什么会跳过失败测试。
容易踩的坑
- 测试逐步镜像实现(change-detector 陷阱)。
- 只盯”100% 覆盖”,从不断言行为。
- 把 flaky 测试留在 main,训练团队对红色 CI 视而不见。
- 修完 bug 才写回归测试——你丢掉了它曾经抓到东西的证明。
- mock 掉你本该测的那个东西。
- 信任会悄悄适应”本该失败的变化”的自愈式 E2E runner。
怎么把结果再推一步
- 永远声明框架和断言库,否则模型会在一个文件里把 Jest 和 Mocha 语法混着用。
- 每条生成的测试都自问”它能抓什么 bug?“答不上就删。
- 先写失败测试再修。它必须在
main上失败、在你分支上通过——这样才是真回归测试。 - 优先表驱动 Prompt:一行一个 case(Vitest/Jest 的
it.each,pytest 的@pytest.mark.parametrize),重复更少、更易扩展。 - 单次 Prompt 测试数控制在 8 到 10 个。再多,模型就开始改个变量名复制同一语义。
FAQ
- 怎么避免 change-detector 测试? 在 Prompt 里描述行为契约(“返回去重排序的字符串”),绝不描述实现。好测试在重构后照样过,只在行为变了时才失败。
- 该告诉模型哪个框架版本? 用项目已经锁定的那个,带大版本。Vitest 3 和 Jest 30 约 95% API 兼容,但
vi.mockvsjest.mock、ESM vs CJS 配置差得足以让一次运行崩掉。把一个现有测试文件的 import 行贴进 Prompt。 - AI 该 mock 还是用真实依赖? 外部边界(HTTP、支付、邮件)mock;进程内纯代码(解析、格式化)保真。把这条规则写进 Prompt,因为各模型默认不一样。
- AI 能识别 flaky 测试吗? 有时能。模板 8 在你把测试和被测代码一起贴时有效。只凭测试名”猜 flaky”基本是瞎猜。
- 一个函数写多少测试? happy path + 3 个边界 + 1 个非法输入是稳妥基线。只有真出过 bug、教会你缺哪个 case 时才加。
- 为什么我改坏了代码 AI 测试还是过? 模型测的是它脑中的代码,不是你的。改一行再跑——还过就说明是噪声。用模板 12 找真正的缺口。2026 年业界的共识很一致:把模型当草稿作者,关键断言自己把关。