我用 AI 给一个模块补单元测试:真正省时间的不是“生成代码”,而是这 4 个步骤

0 阅读5分钟

很多人用 AI 写代码,第一反应是让它“帮我实现一个功能”。但在真实项目里,我更建议先从单元测试开始。

原因很简单:测试的边界更清楚,结果更容易验证,也更适合作为团队引入 AI 编程的第一步。

如果你直接让 AI 改业务代码,它可能会改得很快,但你要花很多时间判断有没有破坏原逻辑。让 AI 先补测试,风险更低,收益也更稳定。

一个典型场景

假设项目里有一个订单价格计算函数:

type OrderItem = {
  price: number;
  quantity: number;
};

type Coupon = {
  type: "amount" | "percent";
  value: number;
};

export function calculatePayable(items: OrderItem[], coupon?: Coupon): number {
  const total = items.reduce((sum, item) => {
    return sum + item.price * item.quantity;
  }, 0);

  if (!coupon) return total;

  if (coupon.type === "amount") {
    return Math.max(0, total - coupon.value);
  }

  if (coupon.type === "percent") {
    return Math.max(0, total * (1 - coupon.value));
  }

  return total;
}

这个函数不复杂,但它已经有几个必须覆盖的点:

  • 没有优惠券时返回原价。
  • 满减券不能减成负数。
  • 折扣券要处理 0、正常折扣、极端折扣。
  • 空商品列表是否允许。
  • 金额精度是否需要统一到分。

很多项目的问题不是“没有 AI”,而是这些规则只存在于开发者脑子里。新人接手、外包交付、需求迭代时,很容易漏。

第一步:别急着让 AI 写测试,先让它列测试矩阵

提示词:

你是一个资深 TypeScript 测试工程师。
请阅读下面的函数,先不要写测试代码。
请输出测试矩阵,包含:
1. 场景名称
2. 输入
3. 期望输出
4. 这个场景覆盖的风险

函数代码:
<粘贴代码>

这个步骤非常关键。因为 AI 直接写测试时,经常只覆盖 happy path。先让它列矩阵,相当于把隐含需求显性化。

你要重点检查 3 件事:

  • 是否覆盖边界值。
  • 是否覆盖异常或不合理输入。
  • 是否把业务规则理解错了。

第二步:让 AI 按现有测试框架生成代码

不要只说“帮我写单测”。要告诉它项目使用的测试工具、文件结构、命名风格。

示例提示词:

基于上面的测试矩阵,用 Vitest 写单元测试。
要求:
1. 使用 describe/it/expect。
2. 文件名为 calculatePayable.test.ts。
3. 每个测试用例名称用中文描述业务场景。
4. 不要 mock 无关内容。
5. 只测试公开函数 calculatePayable。

生成结果可能类似:

import { describe, expect, it } from "vitest";
import { calculatePayable } from "./calculatePayable";

describe("calculatePayable", () => {
  it("没有优惠券时返回商品总价", () => {
    expect(
      calculatePayable([
        { price: 100, quantity: 2 },
        { price: 50, quantity: 1 },
      ]),
    ).toBe(250);
  });

  it("满减券不能把应付金额减成负数", () => {
    expect(
      calculatePayable([{ price: 80, quantity: 1 }], {
        type: "amount",
        value: 100,
      }),
    ).toBe(0);
  });

  it("折扣券按比例计算应付金额", () => {
    expect(
      calculatePayable([{ price: 200, quantity: 1 }], {
        type: "percent",
        value: 0.2,
      }),
    ).toBe(160);
  });
});

第三步:让 AI 反过来审查自己的测试

很多人漏掉了这一步。

AI 生成测试以后,不要马上合并。继续追问:

请审查你刚才写的测试。
重点检查:
1. 有没有只验证实现细节,而不是业务行为?
2. 有没有遗漏边界值?
3. 有没有测试名称和断言不一致?
4. 哪些测试可能在需求变化后变得脆弱?
请只输出问题和改进建议。

这一步经常能发现:

  • 浮点数精度问题没有处理。
  • 折扣券 value 的合法范围没有定义。
  • 空数组返回 0 是否符合业务没有确认。
  • 负价格、负数量没有明确约束。

这些发现比测试代码本身更有价值,因为它会逼你把业务规则讲清楚。

第四步:把 AI 输出变成团队流程

如果只是让 AI 偶尔补几个测试,收益有限。

更好的方式是把它固化成一个 checklist:

  • 改业务代码前,先让 AI 列测试矩阵。
  • 开发完成后,让 AI 补 happy path 和边界测试。
  • PR 前,让 AI 审查测试是否只覆盖了实现细节。
  • Code Review 时,把 AI 发现的问题作为人工 review 的输入,而不是最终结论。

我建议的最小落地方式

不要一开始就全团队推广。选一个低风险模块,做一次完整试点:

  1. 找一个 300-800 行的模块。
  2. 让 AI 输出测试矩阵。
  3. 人工确认业务规则。
  4. 让 AI 生成测试。
  5. 本地跑通。
  6. 人工 review。
  7. 记录节省了多少时间、发现了几个遗漏规则。

如果这个流程跑通,再推广到更多模块。

最后说实话

AI 不会自动让你的项目测试质量变好。它真正有用的地方,是把“测试该覆盖什么”这件事变得更便宜。

程序员最该保留的能力不是手写每一行测试,而是判断:

  • 哪些行为必须被测试锁住。
  • 哪些边界代表真实业务风险。
  • AI 生成的断言是否真的证明了代码正确。

如果你所在团队还没开始用 AI 进入研发流程,我建议从单元测试开始。它最容易验证,也最容易形成正反馈。

我最近也在做小范围的 AI 代码审查和单元测试补齐服务。如果你有一个小仓库或单个模块想试,可以私信我,我先帮你判断适不适合做。