写单元测试一直是个痛点。逻辑简单还好说,遇到边界条件、异常路径,手动写测试用例能烦死人。
现在 AI 编程工具都能一键生成测试了。但效果到底怎么样?不同工具有什么差异?
今天拿 Claude Code、Cursor、GitHub Copilot 三个主流工具做实测,用同一段代码生成测试,看看谁写的测试最靠谱。
一、测试对象:一段有坑的业务代码
先准备一段有代表性的业务代码。这段代码包含正常流程、边界条件和异常处理,足够检验 AI 生成测试的全面性。
# calculator.py
def divide(a, b):
"""安全除法,返回浮点数结果"""
if not isinstance(a, (int, float)):
raise TypeError("参数 a 必须是数字")
if not isinstance(b, (int, float)):
raise TypeError("参数 b 必须是数字")
if b == 0:
raise ValueError("除数不能为零")
return a / b
def safe_list_get(lst, index, default=None):
"""安全获取列表元素,越界返回默认值"""
if not isinstance(lst, list):
raise TypeError("第一个参数必须是列表")
try:
return lst[index]
except IndexError:
return default
这段代码看起来简单,但包含了类型校验、异常抛出、边界处理。好的测试应该覆盖所有这些情况。
二、Claude Code 生成测试
Claude Code 是目前命令行最强的 AI 编程助手。直接用命令让它生成测试:
claude test calculator.py --framework pytest
生成的测试文件 test_calculator.py:
import pytest
from calculator import divide, safe_list_get
class TestDivide:
def test_normal_division(self):
assert divide(10, 2) == 5.0
assert divide(7, 3) == pytest.approx(2.333)
def test_division_by_zero(self):
with pytest.raises(ValueError, match="除数不能为零"):
divide(10, 0)
def test_type_error_for_non_numeric(self):
with pytest.raises(TypeError):
divide("10", 2)
with pytest.raises(TypeError):
divide(10, "2")
def test_float_precision(self):
result = divide(1, 3)
assert isinstance(result, float)
class TestSafeListGet:
def test_normal_access(self):
assert safe_list_get([1, 2, 3], 0) == 1
assert safe_list_get([1, 2, 3], 2) == 3
def test_out_of_bounds_returns_default(self):
assert safe_list_get([1, 2, 3], 10) is None
assert safe_list_get([1, 2, 3], -10) is None
def test_custom_default_value(self):
assert safe_list_get([1, 2, 3], 10, "missing") == "missing"
def test_type_error_for_non_list(self):
with pytest.raises(TypeError):
safe_list_get("not a list", 0)
评分:9/10
Claude Code 生成的测试覆盖了正常值、边界值、异常类型、自定义默认值。结构清晰,用了 pytest.approx 处理浮点精度,还用了 class 分组。唯一小问题是没测负数索引的情况。
三、Cursor Composer 生成测试
Cursor 的 Composer 模式支持多文件编辑,直接选中代码文件让它生成测试:
- 打开 Cursor Composer
- 选中
calculator.py - 输入:
请为这段代码生成完整的 pytest 单元测试
生成的测试:
import pytest
from calculator import divide, safe_list_get
def test_divide():
# 正常除法
assert divide(10, 2) == 5.0
assert divide(7, 3) == pytest.approx(2.333333333)
# 除零错误
with pytest.raises(ValueError):
divide(10, 0)
# 类型错误
with pytest.raises(TypeError):
divide("a", 2)
with pytest.raises(TypeError):
divide(10, [])
def test_safe_list_get():
# 正常取值
assert safe_list_get([1, 2, 3], 0) == 1
# 越界返回默认值
assert safe_list_get([1, 2, 3], 100) is None
# 自定义默认值
assert safe_list_get([1, 2, 3], 5, "default") == "default"
# 类型校验
with pytest.raises(TypeError):
safe_list_get("string", 0)
评分:7.5/10
Cursor 的测试基本能用,覆盖了主要场景。但有几个问题:没有用 class 组织测试、没测负数索引、浮点精度比较不够严谨(手动写了过多小数位)。优点是生成速度快,适合快速补测试。
四、GitHub Copilot 生成测试
Copilot 通过 inline chat 功能生成测试:
- 打开测试文件
test_calculator.py - Ctrl+I 打开 Copilot Chat
- 输入:
Generate comprehensive pytest tests for calculator.py
生成的测试:
import pytest
from calculator import divide, safe_list_get
def test_divide_valid_inputs():
assert divide(4, 2) == 2.0
assert divide(5, 2) == 2.5
assert divide(-4, 2) == -2.0
assert divide(0, 5) == 0.0
def test_divide_by_zero():
with pytest.raises(ValueError):
divide(1, 0)
def test_divide_invalid_types():
with pytest.raises(TypeError):
divide("10", 2)
with pytest.raises(TypeError):
divide(None, 2)
def test_safe_list_get_valid():
assert safe_list_get([10, 20, 30], 0) == 10
assert safe_list_get([10, 20, 30], 2) == 30
def test_safe_list_get_out_of_range():
assert safe_list_get([10, 20, 30], 10) is None
def test_safe_list_get_with_default():
assert safe_list_get([], 0, "default") == "default"
def test_safe_list_get_invalid_input():
with pytest.raises(TypeError):
safe_list_get((1, 2, 3), 0)
评分:8.5/10
Copilot 的测试覆盖了正数、负数、零等边界情况,这点比 Claude Code 做得好。测试命名规范,每个函数都有独立的测试用例。不足之处是没有用 pytest.approx 处理浮点精度,也没对 safe_list_get 的 tuple 输入做类型校验测试。
五、横向对比总结
| 维度 | Claude Code | Cursor | GitHub Copilot |
|---|---|---|---|
| 测试覆盖率 | ★★★★★ | ★★★☆☆ | ★★★★☆ |
| 代码规范性 | ★★★★★ | ★★★☆☆ | ★★★★☆ |
| 边界条件覆盖 | ★★★★☆ | ★★★☆☆ | ★★★★★ |
| 生成速度 | 中等 | 快 | 快 |
| 多语言支持 | 好 | 好 | 一般 |
| 可定制性 | 高(CLI参数) | 中 | 低 |
怎么选?
- 追求质量选 Claude Code:生成的测试最规范,支持 CLI 参数控制测试框架、覆盖率目标,适合 CI/CD 集成。
- 追求速度选 Cursor:Composer 模式下改代码加测试一气呵成,适合日常开发中快速补充测试。
- 通用场景选 Copilot:和 VS Code 深度整合,不需要切换工具就能生成测试,适合已经订阅 Copilot 的团队。
六、提高 AI 生成测试质量的 3 个技巧
不管用哪个工具,这 3 招能让生成的测试质量大幅提升:
1. 提供上下文
不要只丢一个函数过去。把相关的类型定义、依赖模块一起给 AI 看。比如:
请为以下代码生成 pytest 测试,注意:
- 项目使用 pytest 框架
- 需要覆盖所有异常路径
- 使用 pytest.approx 处理浮点比较
2. 指定测试框架和风格
明确告诉 AI 你要用什么框架(pytest/unittest)、断言风格(assert/raises)、是否需要参数化测试。指令越具体,输出越精准。
3. 人工审查必不可少
AI 生成的测试不是万能的。重点检查:
- 是否覆盖了所有
raise分支 - 边界值是否合理(比如除数为 0 之外,有没有考虑 NaN、Infinity)
- 测试之间是否有依赖关系(好的测试应该是独立的)
七、结语
AI 生成单元测试已经能从「勉强能用」进化到「大部分直接合并」。Claude Code 在质量和可控性上领先,Cursor 胜在开发体验流畅,Copilot 则胜在生态整合。
你平时用哪个工具生成测试?效果怎么样?评论区聊聊。