2022年AI大模型爆发,我尝试用AI生成单元测试,踩了不少坑。

本文分享我的实战经验,包括用过的工具、具体的流程、踩过的坑、解决方案,以及最佳实践。

一、为什么用AI生成单元测试

1. 单元测试的痛点

写单元测试,是很多开发者的痛点。

  • 费时费力
  • 覆盖率上不去
  • 写了很多,但质量不高
  • 维护成本高

特别是老项目,代码复杂,写测试更难。

2. AI的机会

AI大模型的出现,给单元测试带来了新的可能。

  • AI可以理解代码逻辑
  • AI可以快速生成测试用例
  • AI可以覆盖各种边界情况
  • 大大提高效率

于是,我开始尝试用AI生成单元测试。

3. 目标

我的目标:

  • 提高测试覆盖率
  • 减少写测试的时间
  • 保证测试质量
  • 让团队更愿意写测试

二、用过的工具

1. GitHub Copilot

GitHub Copilot是我最早用的AI编程工具。

  • 集成在IDE里
  • 写代码时自动提示
  • 可以生成测试代码
  • 但需要手动引导

优点:方便,集成度高。 缺点:生成的测试比较简单,覆盖率有限。

2. ChatGPT

后来,我开始用ChatGPT生成测试。

  • 把代码贴给ChatGPT
  • 让它生成单元测试
  • 可以反复调整
  • 生成的测试质量不错

优点:质量高,可以对话调整。 缺点:需要手动复制粘贴,效率一般。

3. 专门的测试生成工具

还试过一些专门的AI测试生成工具。

  • 比如CodiumAI、Diffblue等
  • 可以自动分析代码
  • 自动生成测试
  • 集成到CI/CD

优点:自动化程度高。 缺点:有些工具收费,定制性差。

三、我的工作流程

经过摸索,我形成了一套工作流程。

1. 第一步:准备代码

先把要测试的代码准备好。

  • 确保代码结构清晰
  • 有明确的输入输出
  • 尽量减少副作用
  • 有必要的注释

代码越清晰,AI生成的测试越好。

2. 第二步:给AI上下文

给AI足够的上下文。

请为以下代码生成单元测试:

要求:
1. 使用Jest框架
2. 覆盖正常情况和边界情况
3. 测试函数命名清晰
4. 每个测试只测一个点
5. 包含错误处理的测试

代码:
{code}

相关的类型定义:
{types}

依赖的模块:
{dependencies}

上下文越充分,生成的测试越准确。

3. 第三步:生成测试

让AI生成测试。

  • 先让AI生成一版
  • 看看质量如何
  • 如果不满意,调整提示词
  • 反复迭代,直到满意

4. 第四步:审查和修改

AI生成的测试,一定要审查。

  • 测试逻辑是否正确
  • 有没有覆盖关键路径
  • 有没有虚假测试(看起来在测,实际没测)
  • 命名和风格是否统一

审查后,手动修改不完善的地方。

5. 第五步:运行测试

运行生成的测试。

  • 看是否通过
  • 看覆盖率
  • 看有没有误报
  • 修复失败的测试

6. 第六步:维护

测试生成后,还要维护。

  • 代码变更时,更新测试
  • 定期检查测试质量
  • 删除无用的测试
  • 保持测试的有效性

四、踩过的坑

1. 坑一:AI生成的测试是"假"的

最常见的坑:AI生成的测试看起来像测试,实际没测什么。

比如:

// 看起来在测,实际没测
test('add function works', () => {
  const result = add(1, 2);
  expect(result).toBeDefined();  // 只要不报错就通过
});

这个测试只要函数不抛异常就通过,根本没验证结果。

解决方案:

  • 审查测试时,看断言是否有意义
  • 要求AI生成具体的断言
  • 比如expect(result).toBe(3),而不是toBeDefined()

2. 坑二:AI不理解业务逻辑

AI可能不理解业务逻辑,生成的测试不符合业务需求。

比如:

  • 业务规则是"用户年龄必须大于18岁"
  • AI生成的测试可能测的是"年龄大于0"
  • 没有覆盖真正的业务规则

解决方案:

  • 给AI提供业务规则说明
  • 让AI先理解业务,再生成测试
  • 人工审查业务相关的测试

3. 坑三:AI生成的测试有幻觉

AI可能会"幻觉"出不存在的函数或属性。

比如:

  • 代码里没有getUserById函数
  • AI生成的测试里调用了这个函数
  • 测试根本跑不通

解决方案:

  • 运行测试,发现不存在的函数
  • 修正测试
  • 给AI更准确的代码上下文

4. 坑四:测试覆盖率虚高

AI生成的测试,可能覆盖率很高,但实际质量很差。

  • 很多测试只是调用函数,不验证结果
  • 覆盖率上去了,但没什么用
  • 给人一种"测试很充分"的错觉

解决方案:

  • 不要只看覆盖率
  • 要看测试的质量
  • 用变异测试(mutation testing)验证测试有效性
  • 人工审查关键路径的测试

5. 坑五:AI生成的测试风格不统一

不同时间生成的测试,风格可能不统一。

  • 命名方式不一样
  • 结构不一样
  • 断言风格不一样
  • 代码可读性差

解决方案:

  • 在提示词里明确风格要求
  • 用ESLint/Prettier统一格式
  • 建立团队的测试规范
  • 人工调整风格

6. 坑六:过度依赖AI

最大的坑:过度依赖AI。

  • 不再自己思考测试逻辑
  • AI生成什么就用什么
  • 不审查,不修改
  • 测试质量越来越差

解决方案:

  • AI是辅助,不是替代
  • 开发者要理解测试逻辑
  • 人工审查是必须的
  • 关键测试自己写

五、最佳实践

1. 提示词要详细

好的提示词,是生成好测试的关键。

包括:

  • 测试框架
  • 断言风格
  • 命名规范
  • 要覆盖的场景
  • 业务规则
  • 代码上下文

提示词越详细,生成的测试越好。

2. 分模块生成

不要一次生成整个项目的测试。

  • 一个函数一个函数地生成
  • 一个模块一个模块地生成
  • 每生成一个,就审查和运行
  • 确保质量

3. 人工审查是必须的

AI生成的测试,一定要人工审查。

  • 看逻辑是否正确
  • 看断言是否有意义
  • 看是否覆盖了关键路径
  • 看是否符合业务需求

人工审查,是保证质量的关键。

4. 结合传统方法

AI生成 + 传统方法,效果最好。

  • AI生成基础测试
  • 人工补充边界情况
  • 用覆盖率工具检查
  • 用变异测试验证

5. 持续维护

测试生成后,要持续维护。

  • 代码变更时,更新测试
  • 定期检查测试质量
  • 删除过时的测试
  • 保持测试的有效性

六、工具推荐

1. GitHub Copilot

  • 适合:日常开发中快速生成测试
  • 优点:集成度高,方便
  • 缺点:生成的测试比较简单

2. ChatGPT / Claude

  • 适合:生成复杂的测试
  • 优点:质量高,可以对话调整
  • 缺点:需要手动复制粘贴

3. CodiumAI

  • 适合:自动化生成测试
  • 优点:专门做测试生成,集成度高
  • 缺点:有些功能收费

4. Diffblue Cover

  • 适合:Java项目
  • 优点:自动化程度高
  • 缺点:只支持Java

七、写在最后

用AI生成单元测试,是一个很好的方向。

但AI不是万能的,它生成的测试需要人工审查和修改。把AI当成助手,而不是替代,才能发挥最大的价值。

2023年了,AI技术发展很快,测试生成的质量也在不断提高。但不管AI多强,理解业务逻辑、保证测试质量,还是需要开发者自己来。

最后,用一句话总结:"AI生成单元测试,能提高效率,但不能替代人工审查。好的提示词 + 人工审查 + 持续维护,才能生成高质量的测试。"

愿你用好AI,写出高质量的测试。