假设 AI 生成的退款函数只改了一行:amount <= balance。正常金额看起来没有问题,但负数也会被允许。diff 能告诉你改了什么,却不能证明边界输入会怎样运行。本文用一个可执行的小例子,把审查从文本扩展到行为。
适合读者:会阅读 Pull Request、了解基本测试和 CI 的开发者。示例只需要 Python 3 标准库。
Why:代码审查看到的是变化,不是完整契约
审查者容易聚焦新增的几行,却忽略旧调用方、异常输入和权限边界。AI 生成的代码尤其容易给出“结构完整”的错觉:函数名、注释和测试名字都合理,关键断言却可能只覆盖正常路径。判断一笔退款能否通过,必须先回答“零、负数、余额边界和超额金额分别应该怎样”。
What:四层行为验证
diff 与需求 → 输入/输出契约
↓
正常值、边界值、非法值
↓
调用链与外部依赖检查
↓
CI 验证 → 发布后观察
第一层核对需求与函数契约;第二层用表驱动测试覆盖边界;第三层追到真正的调用方、数据库或外部 API,确认异常会被正确处理;第四层让 CI 重复执行,并在发布后观察错误率。单元测试不能替代真实链路测试,但能快速暴露最基本的反例。
How:为一行判断补上反例
下面的代码可保存为 test_refund.py,运行 python3 -m unittest -q test_refund.py。先把函数改回 return amount <= balance,负数用例会失败;再恢复正确判断,测试应通过。
import unittest
def refund_allowed(balance, amount):
# 退款必须为正数,且不能超过可退余额
return 0 < amount <= balance
class RefundPolicyTest(unittest.TestCase):
def test_boundaries(self):
cases = [(1, True), (100, True), (0, False), (-1, False), (101, False)]
for amount, expected in cases:
with self.subTest(amount=amount):
self.assertEqual(refund_allowed(100, amount), expected)
if __name__ == "__main__":
unittest.main()
这个例子验证的是纯函数。实际退款还要测余额读取、重复请求、并发提交和失败后的补偿。审查时沿着调用链问:谁能传入 amount?金额单位是否一致?超时重试是否会重复退款?这些问题无法只从一行 diff 得到答案。
把检查落到 PR 与 CI
- 在 PR 描述中写出验收条件和至少一个失败反例,而不是只贴“测试已通过”。
- 要求正常、边界和非法输入的断言;对权限、幂等性和副作用补集成测试。
- 检查新增依赖与脚本的来源、权限和版本;CI 使用锁定依赖与最小权限。
- 把测试命令与结果附在 PR 上;发布后观察对应接口与日志,出现回归有明确回退方式。
结论:先找一个能推翻实现的输入,再判断代码是否值得合并。延伸阅读:GitHub Actions 文档、OpenSSF Scorecard。
