让 AI 帮你写好单元测试:从 0 覆盖到 80%
用 AI 写单元测试 2026 实战:三段式提示词(覆盖目标 → 边界条件 → mock 策略)、Vitest / Jest / Pytest / Go test 框架适配、让 AI 自查测试质量的 review 提示词,以及 CI 跑通的踩坑。
发布 2026-08-02更新 2026-10-17核实 2026-10-17一句话结论
让 AI 写单元测试,已经从「能生成几行」进化到「能跑到 80% 覆盖」。但前提是给对提示词——无脑「帮我写测试」生成的东西往往只覆盖 happy path、边界缺失、mock 乱飞。用三段式提示词(覆盖目标 → 边界条件 → mock 策略),并让 AI 自查测试质量,效果立竿见影。
三段式提示词
不要只说「给这个函数写测试」。把任务拆成三段喂给 AI:
第 1 段:覆盖目标
给 src/utils/format.ts 里的 formatPrice / formatDate / slugify 写单元测试。
目标:行覆盖 ≥ 90%,每个导出函数至少一个用例。
明确覆盖率数字,AI 才会主动补分支。
第 2 段:边界条件
重点覆盖以下边界:
- formatPrice:0、负数、超大数、undefined、null、NaN
- formatDate:非法日期字符串、时区、闰秒
- slugify:中文、空格、特殊字符、空串
边界是 AI 最容易漏的,显式列出来它才会补。
第 3 段:mock 策略
- 涉及 fetch / 外部 API 的,用 vi.mock 隔离,不要真发请求
- 涉及 Date.now() 的,用 vi.useFakeTimers() 固定时间
- 涉及文件系统的,用临时目录或 mock fs
- 不要为了覆盖率 mock 掉被测函数本身
mock 策略写清楚,生成的测试才「可信」而非「自欺欺人」。
框架适配
三段式结构通用,差异只在断言风格和 runner 命令:
| 框架 | 安装 | 测试文件约定 | 关键 API | 跑命令 |
|---|---|---|---|---|
| Vitest | npm i -D vitest | *.test.ts | describe/it/expect/vi | vitest run |
| Jest | npm i -D jest | *.test.js | describe/test/expect/jest | jest |
| Pytest | pip install pytest | test_*.py | def test_* / assert | pytest |
| Go test | 内置 | *_test.go | func Test* / t.Run | go test ./... |
Vitest 示例(AI 生成后你 review)
import { describe, it, expect, vi, afterEach } from 'vitest'
import { formatPrice } from '../src/utils/format'
describe('formatPrice', () => {
it('正常金额格式化', () => {
expect(formatPrice(1234.5)).toBe('¥1,234.50')
})
it('负数与 0', () => {
expect(formatPrice(0)).toBe('¥0.00')
expect(formatPrice(-5)).toBe('-¥5.00')
})
it('非法输入抛错', () => {
expect(() => formatPrice(NaN)).toThrow()
expect(() => formatPrice(undefined as any)).toThrow()
})
})
Pytest 示例
import pytest
from utils import slugify
def test_slugify_basic():
assert slugify("Hello World") == "hello-world"
def test_slugify_chinese():
assert "python" in slugify("Python 编程")
def test_slugify_empty():
assert slugify("") == ""
Go test 示例
func TestFormatPrice(t *testing.T) {
got := formatPrice(1234.5)
want := "¥1,234.50"
if got != want {
t.Errorf("got %q want %q", got, want)
}
}
让 AI 自查测试质量(review 提示词)
生成后别直接 Accept,让 AI 当 reviewer:
review 刚才生成的测试,检查:
1. 有没有「假覆盖」——只断言不抛错但没验证返回值
2. 边界是否真覆盖(不是只测 happy path)
3. mock 是否过度(mock 掉了被测逻辑本身)
4. 用例之间是否有依赖(必须能独立运行)
给出问题清单并修复。
AI 之家 观点:AI 生成的测试最大的陷阱是「假覆盖」——
expect(true).toBe(true)或只断言「不抛异常」。CI 上绿了,其实啥也没测。强制它自查「有没有验证返回值」能过滤掉大半垃圾用例。
覆盖率门槛设置
| 阶段 | 建议门槛 | 理由 |
|---|---|---|
| 新项目起步 | 60% | 别一上来卡太死,先有再说 |
| 稳定模块 | 80% | 核心逻辑达标 |
| 关键路径(支付/权限) | 90%+ | 出错代价高 |
用 vitest --coverage / pytest --cov / go test -cover 看实际数字,逐步提。
CI 上跑通的踩坑
- 测试依赖执行顺序:AI 偶尔写出有状态的测试(共享全局变量),单独跑过、CI 并行跑挂。要求「每个用例独立」。
- 快照测试滥用:AI 爱用
toMatchSnapshot(),但快照一旦生成就永远「通过」。关键逻辑用显式断言。 - 假定时器未清理:
vi.useFakeTimers()后忘了afterEach(vi.useRealTimers),污染下一个测试。 - 覆盖率门槛设太高:新项目直接设 80% 会卡住 CI。建议先 60% 起步,逐步提。
- AI 改了源码来「让测试通过」:review 时注意它是否偷偷放宽了函数逻辑。接 CodeRabbit 在 PR 卡一道质量门更稳。
真实案例:从 0 到 82% 覆盖
一个 2000 行 TS 工具库,原本 0 测试。用三段式提示词分批生成:
- 第 1 批:纯函数(format/parse)→ 覆盖 95%
- 第 2 批:带 IO 的函数(fetch 包装)→ mock 后覆盖 80%
- 第 3 批:边界与异常 → 总覆盖 82%
- AI 自查修掉 6 处「假覆盖」用例
总耗时约 2 小时(含 review),人力约为纯手写的 1/4。
什么时候用 / 别用
适合用 AI 生成测试的场景
- 纯函数与工具库:输入输出明确、无隐藏状态,AI 生成质量最高,也最容易验收。
- 边界与异常分支补齐:人写测试最容易漏的就是「空值、超长、非法编码、并发重复提交」这类不性感的分支,AI 反而有耐心枚举。
- 给存量代码补回归网:重构前先铺一层测试,能立刻把「改坏了不知道」变成「改坏了 30 秒内知道」。
- 跨语言的同类测试迁移:同一种断言换框架重写,机械性高、出错率低。
不适合用的场景
- 需要真实外部依赖的集成测试:AI 极易写出「mock 掉一切」的测试——跑得飞快,什么也测不出来。数据库约束、真实序列化、网络重试这些只能在真依赖上暴露的问题,mock 会一并盖掉。
- 性能与并发断言:耗时与竞态天然不稳定,AI 生成的阈值往往拍脑袋。要测就在 CI 上用固定基线,不要写死毫秒数。
- 安全相关断言:AI 可能补上一个「看起来通过」的鉴权测试,实际绕过了真正的校验路径。这类测试必须人工审。
- 业务逻辑本身就是需求来源的时候:如果你说不清「正确行为是什么」,AI 只会把当前实现(含 bug)固化成断言。
验收判据:怎么判断生成的测试是真的
这是本节最该带走的东西。 AI 生成的测试有一个典型失败模式——「假覆盖」:覆盖率涨了,但断言弱到永远不会失败。
三条可执行的判据:
- 变异测试(mutation testing):故意改坏一行源码(把
>改成>=、删掉一个if分支),看测试是否变红。不变红 = 这条测试没在测它。这是唯一能系统性识别假覆盖的手段。 - 断言密度检查:抽查几段,只有
expect(...).toBeDefined()/assert result is not None这类「存在性断言」的,几乎都是假覆盖。好的测试断言的是具体值或具体行为变化。 - 反向用例成对:每个「应该成功」的用例旁边,应该有一个「应该失败且失败方式明确」的用例。只有正向用例的测试文件,通常漏掉了整类边界。
本文正文提到的「82% 覆盖」是行覆盖率。覆盖率数字与测试质量之间没有必然联系——一条断言能覆盖十行代码,但可能一条都没真正验证。把覆盖率当 KPI 的团队,最终都会收获一堆假覆盖。
更新说明
- 2026-10-17:补充「什么时候用 / 别用」与「验收判据」两节。核心是把「生成了多少测试」的度量换成「多少测试能在代码改坏时变红」。
- 待核实:本文正文涉及的 Vitest / Pytest / Go testing 命令随框架版本变化,本站未逐版本回归,请以各框架官方最新文档为准。
相关阅读
- 工具卡:Cursor | Claude Code | CodeRabbit
- 评测:国产 Copilot 四强横评(单测生成维度)
- 方案:AI 代码评审工作流
- Prompt:测试生成提示词
来源说明:本文基于 Vitest / Pytest / Go testing 官方文档、CodeRabbit 评审能力说明及 AI 之家 编辑部实践归纳。框架版本迭代快,命令以官方最新文档为准。
相关工具
Aider vs Claude Code:终端 AI 编程双雄怎么选
Aider vs Claude Code 2026 选型对比:开源 BYOK 多模型 vs Anthropic 订阅长任务 Agent,从编程能力、多模型支持、价格、Git 集成、国内可用性和适合人群判断,帮你选对终端 AI 编程工具。
Cursor vs Aider:GUI IDE 还是 CLI?2026 对比
Cursor vs Aider 2026 选型对比:GUI IDE vs Git 原生 CLI,从 Composer vs Architect 双模型、Tab 补全、多模型 BYOK、价格计费、开源与否和适合人群判断,帮开发者选对。Cursor 是闭源 VS Code fork 月费 $20,Aider 是开源 Apache-2.0 CLI 自带 API key。
Augment Code vs Cursor:企业 AI 编程怎么选?Context Engine vs AI IDE 对比
Augment Code vs Cursor 2026 选型对比:Context Engine 全仓索引的企业 AI 平台 vs SpaceX 收购的 AI IDE 天花板,从形态、Context 覆盖、长任务、价格、合规、中文支持和适合人群 8 个维度判断,帮你选对企业 AI 编程工具。
Claude Code vs Cline:CLI AI Agent 怎么选?2026 对比
Claude Code vs Cline 2026 选型对比:Anthropic 官方闭源 CLI Agent vs Apache-2.0 开源 VS Code 插件。从模型绑定、工作流、MCP 支持、价格、隐私和适合人群 6 个维度帮你选对 CLI AI 编程工具。
Claude Code vs Codex CLI:终端 AI Agent 双雄对比
Claude Code vs Codex CLI 2026 选型对比:Anthropic 与 OpenAI 两大官方终端 Agent 的模型、长任务、MCP 生态、Windows 支持、订阅打包价格和国内可用性全方位对比,帮你判断该用哪个终端 AI Agent,以及能不能两个一起用。
Claude Code vs Crush:Anthropic 官方 vs 多模型 TUI(2026 实测选型)
Claude Code vs Crush 怎么选:Anthropic 官方 CLI(长任务最稳),对上 Charmbracelet 开源 TUI(多模型切换 + LSP)。按模型、长任务、价格对比。
AI 代码审查工具对比 2026:CodeRabbit、Qodo、Greptile、Ellipsis 怎么选
AI 代码审查工具 2026 横评:对比 CodeRabbit、Qodo、Greptile、Ellipsis 的 PR Review 质量、Bug 检出率、噪音率、价格和适合团队。附 GitHub 接入建议、双挂组合、避坑清单,帮助研发团队选择 AI Code Review 工具。
AI 编程工具选型决策树:30 个场景告诉你该用哪个
整合 AI 之家 编辑部 11 篇深度评测的结论:按角色、预算、规模、网络环境四维度的 AI 编程工具决策树。Cursor / Claude Code / Aider / Trae / v0 / Lovable 等主流工具一图看完该选哪个,附 30 个真实场景对应表。
2026 年 AI 编程工具全景图:18 款实测排行
2026 年 AI 编程工具全景:18 款实测按 IDE / CLI / 插件 / Agent / Builder / 本地分桶,给出 Top 10 排行、5 维评分方法论,以及国内 / 海外 / 学生党的选型建议。