AI 辅助测试与代码审查
AI 在测试与审查这两件事上性价比最高,也最容易产生虚假安全感:它能在几秒内写出二十个测试用例,也能一本正经地把通过当成正确。用好它的方式只有一种——让它负责穷举与提问,让运行结果与人工判断负责结论。
让它生成边界用例与反例
顺利路径的测试人人都会写,真正的价值在边界与反例。把「想边界」这件事明确交给它,并强制它按类别穷举。
| 边界类别 | 要问的具体问题 | 典型遗漏 |
|---|---|---|
| 空与缺 | 空数组、空字符串、字段缺失 | 只测非空数据 |
| 数量极值 | 0、1、2、最大条数、超长字符串 | 只测「几条正常数据」 |
| 数值边界 | 0、负数、小数、金额为分、精度 | 把 0 当成缺失 |
| 时间边界 | 跨天、跨月、时区、夏令时 | 只测同一时刻 |
| 顺序与并发 | 乱序输入、重复调用、并发写 | 假设输入有序 |
| 非法输入 | 类型不符、超范围、注入字符 | 只测合法输入 |
| 状态依赖 | 重复调用、先删后查、中断恢复 | 只测一次性调用 |
请为下面这个函数设计测试用例,只输出用例清单,先不要写代码。
函数:mergeOrders(orders) —— 按 userId 合并订单,返回 orderCount、totalAmount、首末时间。
要求:
1) 按类别穷举:空与缺失、数量极值、数值边界、时间边界、顺序与并发、非法输入、状态依赖;
2) 每条用例写成一行:编号 | 输入(写成可直接使用的字面量)| 期望输出 | 这条用例想抓住的 bug;
3) 至少给 3 条「反例」:看起来合理但输出应当报错或返回空的输入;
4) 明确标出哪些用例你只是推测期望值、需要我去确认业务规则;
5) 最后指出这个函数规格里你认为最含糊的一点,以及你据此做了哪种假设。
补单测模板:让它写,让你判断
写完用例清单再让它落成代码,模板要求固定,避免它写出一堆永不失败的测试。
把上面确认过的用例清单写成单元测试,遵守以下要求:
1) 一个用例一个测试函数,测试名用中文或英文描述行为,不要用 test1、test2;
2) 每个测试只断言一件事,断言消息里带上实际值与期望值;
3) 必须包含至少 2 个异常路径测试(断言会抛出指定错误),不能只有顺利路径;
4) 不使用真实数据库、网络与时间:时间相关的部分抽成可注入的参数,或用固定时钟;
5) 测试数据必须内联写清,不要靠共享的全局 fixture 猜数据;
6) 不要为了让测试通过而修改被测代码;如果被测代码有问题,停下来告诉我。
写完后回答:这些测试里,哪一条如果被删掉,你写的某段代码即使有 bug 也不会被发现?
# 跑新增测试,确认它们真的在断言
pytest -q tests/test_merge_orders.py -v
# 关键一步:故意改坏一处逻辑,确认测试会变红,然后改回
git stash list && git diff --stat
pytest -q tests/test_merge_orders.py # 期望:至少一条失败
git checkout -- src/merge_orders.py
# 看覆盖情况,重点看新增分支是否被覆盖
pytest -q --cov=src --cov-report=term-missing | head -20
故意改坏一次、确认测试会红,是判断测试有没有价值的最低成本实验。一条永远不会失败的测试,比没有测试更危险。
第二双眼睛:检查清单式 review
让它做 review 时,最有用的不是「结论」,而是「你没注意到的问题」。所以要求它逐项回答,而不是自由发挥。
| 审查维度 | 让它回答的问题 |
|---|---|
| 需求对齐 | 这个改动真的实现了需求里的哪一条?有没有做需求之外的事? |
| 正确性 | 边界、空值、并发、精度、时区是否有问题? |
| 错误处理 | 哪些异常被吞掉了?失败时调用方会看到什么? |
| 安全 | 有没有越权、注入、敏感信息落日志? |
| 兼容性 | 接口字段、数据库结构、配置变更是否向后兼容? |
| 测试 | 覆盖了哪些分支?哪些分支没有人测? |
| 可维护性 | 命名、重复、复杂度;本次是否引入了不必要的抽象? |
你是一名审查者,请审查 /tmp/review.diff。要求:
1) 逐项回答下表维度,每个维度开头写「有问题 / 无问题 / 无法判断」;
2) 每条问题必须引用具体文件名与行号,并粘贴相关代码片段作为证据;
3) 按严重程度分成三档:阻断(必须改)、重要(建议改)、提示(可记录);
4) 单独列一节「本次改动没人测试的路径」,写清是哪条分支、为什么没有测试;
5) 单独列一节「我不确定的地方」,说明需要补充什么信息才能判断;
6) 不要输出「建议加注释」「注意代码规范」这类没有具体指向的意见。
最后给出一句话结论:可以直接合并 / 修改后合并 / 需要重新设计。
它不能替代运行与验证
| 任务 | AI 能做 | 只有运行/人能确认 |
|---|---|---|
| 写测试 | 生成用例与骨架 | 测试是否真的失败过、断言是否有意义 |
| 判断 bug | 提出假设与可能原因 | 哪个原因成立,需要实验或日志 |
| 审查 diff | 按清单逐项排查 | 变更是否符合业务语义 |
| 性能问题 | 指出可疑点 | 实际耗时、内存、连接数数据 |
| 安全评估 | 指出常见风险模式 | 真实攻击面与权限配置 |
| 上线判断 | 给出检查清单 | 是否可发布,风险由谁承担 |
请把这次交付的「验证状态」写清楚,分三栏:
1) 已验证:哪些结论是你实际运行或读取输出得到的,附上命令与结果;
2) 未验证:哪些是你的推断,说明需要什么条件才能验证;
3) 无法验证:哪些依赖线上环境、真实数据或人工判断。
不要用「应该没问题」「理论上可行」这类句子替代前两栏的内容。
常见坑
| 坑 | 后果 | 规避 |
|---|---|---|
| 全盘接受它写的测试 | 测试全绿但掩盖 bug | 故意改坏代码验证测试会红 |
| 只测顺利路径 | 边界问题上线才暴露 | 强制按类别穷举边界与反例 |
| 让它同时写代码和测试 | 测试迁就实现的错误 | 先写用例清单,再写测试 |
| 把 review 意见当命令 | 机械照改引入新问题 | 逐条判断,问清依据 |
| 相信「已通过审查」 | 假安全感 | 自己看 diff 与运行结果 |
| 用真实数据造测试数据 | 数据泄漏 | 内联构造假数据 |
小结:让 AI 穷举边界与反例、按模板补单测、按清单做 review,它就能当一双便宜好用的眼睛;但测试必须验证过「会失败」,根因必须由实验确认,合并与上线的判断权始终在人手上——它写的测试和意见,都要由你负责。