跳到主内容
AIHO 2026 全新改版上线
单元测试aivitestpytest工作流测试

让 AI 帮你写好单元测试:从 0 覆盖到 80%

发布 2026-08-02更新 2026-08-02核实 2026-08-02

一句话结论

让 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跑命令
Vitestnpm i -D vitest*.test.tsdescribe/it/expect/vivitest run
Jestnpm i -D jest*.test.jsdescribe/test/expect/jestjest
Pytestpip install pytesttest_*.pydef test_* / assertpytest
Go test内置*_test.gofunc Test* / t.Rungo 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. 用例之间是否有依赖(必须能独立运行)
给出问题清单并修复。

AIHO 观点:AI 生成的测试最大的陷阱是「假覆盖」——expect(true).toBe(true) 或只断言「不抛异常」。CI 上绿了,其实啥也没测。强制它自查「有没有验证返回值」能过滤掉大半垃圾用例。

覆盖率门槛设置

阶段建议门槛理由
新项目起步60%别一上来卡太死,先有再说
稳定模块80%核心逻辑达标
关键路径(支付/权限)90%+出错代价高

vitest --coverage / pytest --cov / go test -cover 看实际数字,逐步提。

CI 上跑通的踩坑

  1. 测试依赖执行顺序:AI 偶尔写出有状态的测试(共享全局变量),单独跑过、CI 并行跑挂。要求「每个用例独立」。
  2. 快照测试滥用:AI 爱用 toMatchSnapshot(),但快照一旦生成就永远「通过」。关键逻辑用显式断言。
  3. 假定时器未清理vi.useFakeTimers() 后忘了 afterEach(vi.useRealTimers),污染下一个测试。
  4. 覆盖率门槛设太高:新项目直接设 80% 会卡住 CI。建议先 60% 起步,逐步提。
  5. 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。

相关阅读

来源说明:本文基于 Vitest / Pytest / Go testing 官方文档、CodeRabbit 评审能力说明及 AIHO 编辑部实践归纳。框架版本迭代快,命令以官方最新文档为准。