乐于分享
好东西不私藏

AI 生成代码上线前,必须过的 5 道验证关

AI 生成代码上线前,必须过的 5 道验证关

这篇文章解决什么问题

很多开发者用 AI 编码助手写代码很快,但上线前往往只做了「跑通测试」这一步。这篇教程给出一套最小可执行的 5 道验证关,帮你在提交 PR 前把 AI 代码里常见的隐患挡在门外。

  • • 适合谁看:日常用 Cursor、Copililot、Claude Code 等 AI 编码工具的开发者
  • • 看完能做到什么:建立一套可复用的提交前自检流程,不靠运气,靠清单

背景

AI 编码助手现在能生成看起来很正确的代码,但常见问题包括:

  • • 看起来跑通了,边界条件没覆盖
  • • 引入了项目里没有的依赖或不兼容的 API
  • • 安全问题(SQL 注入、路径遍历、硬编码密钥)
  • • 风格不统一、命名不规范、缺乏必要注释
  • • 生成了「幻觉」代码:调用不存在的函数、错误的参数顺序

这 5 道关不是要你全人工审,而是把最容易出问题、后果最重的项固化成清单,配合工具自动化,几分钟跑完,心情踏实再提交。


前提条件

  • • 已在项目里配置基础工具链:eslint / ruff / golangci-lint 等(按语言)
  • • CI 里跑单测 + 类型检查(TypeScript 用 tsc --noEmit,Python 用 mypy,Go 用 go vet
  • • 有基础的安全扫描工具:semgrepbanditgosecnpm audit / pip-audit / govulncheck
  • • Git hooks 工具:lefthookpre-commit(可选,用于本地拦截)

第一关:静态检查与类型检查 —— 拦住语法与类型错误

做什么:跑项目配置的 linter + 类型检查器。

为什么:AI 最容易犯的低级错是类型不匹配、未使用变量、导入路径错、弃用 API。这些全是静态工具能秒查出来的。

命令示例

# TypeScript / JavaScript
npm run lint          # eslint
npx tsc --noEmit      # 类型检查

# Python

ruff check .
mypy .

# Go

golangci-lint run
go vet ./...

预期结果:零报错、零警告(或仅剩已知可接受的 legacy 警告)。

出错先查什么

  • • 报错文件是否为 AI 新增/修改的文件
  • • 错误类型是否为类型不匹配、未定义符号、弃用 API
  • • 如果是第三方库类型缺失,补 @types/xxxtypes-xxx,别直接 any

第二关:单测覆盖率与核心路径跑通 —— 拦住逻辑漏洞

做什么:跑全量测试,重点看新增/修改代码的覆盖率

为什么:AI 生成的代码往往「主流程跑通」,边界条件、异常分支、空值处理全靠运气。覆盖率能量化暴露这些盲区。

命令示例

# JavaScript / TypeScript (jest/vitest)
npm test -- --coverage --collectCoverageFrom='src/**/*.ts'

# Python (pytest)

pytest --cov=your_package --cov-report=term-missing

# Go

go test -coverprofile=coverage.out ./...
go tool cover -func=coverage.out | grep -E '(new_file|modified_file)'

预期结果

  • • 全量测试通过
  • 新增/修改文件的行覆盖率 ≥ 80%(核心业务逻辑建议 ≥ 90%)
  • • 关键分支(错误处理、空值、边界值)有对应测试用例

出错先查什么

  • • 哪个函数/分支没覆盖到 → 补测试,或确认该分支真不可达
  • • 测试失败是否为 AI 生成的测试代码本身有问题(常见:mock 不全、断言写反)

第三关:安全扫描 —— 拦住显性安全隐患

做什么:跑语言对应的安全扫描器,专门查 AI 易引入的问题。

为什么:AI 训练数据里有大量不安全代码片段,容易生成:拼接 SQL、直接用用户输入拼路径、硬编码密钥、用弱随机数、未校验重定向目标。

命令示例

# 通用(多语言)
semgrep scan --config=auto .

# Python

bandit -r .

# Go

gosec ./...

# 依赖漏洞

npm audit          # Node.js
pip-audit          # Python
govulncheck ./...  # Go

预期结果

  • • 无 High/Critical 级别漏洞
  • • Medium 级别漏洞需人工评估:是否为误报、是否可通过升级依赖修复、是否需加防护代码
  • • 依赖漏洞:无未修复的 Critical/High CVE

出错先查什么

  • • 报警代码是否为 AI 新增
  • • 是否为误报(如:参数化查询被误判为拼接 SQL)
  • • 依赖漏洞能否直接升级修复,还是需加缓解措施

第四关:代码风格与规范一致性 —— 拦住「看起来不像团队写的」代码

做什么:跑格式化工具检查,对比团队约定的命名、注释、结构规范。

为什么:AI 生成的代码风格常与项目既有代码不一致:命名风格混用、注释缺失或过度、错误处理模式不统一。这会增加后续维护认知负荷。

命令示例

# 格式化检查(不修改,只报差异)
prettier --check .          # JS/TS/JSON/MD
black --check .             # Python
gofmt -l .                  # Go

# 命名/结构规范(需团队自定义规则)

# 例如:eslint-plugin-import-order、pylint-naming、golint 自定义规则

预期结果

  • • 格式化检查通过(或仅有极少量可自动修复的差异)
  • • 关键函数/类有必要的文档注释(公共 API 必须有)
  • • 错误处理模式与项目既有代码一致(如:统一用 Result 类型、统一 try/catch 位置)

出错先查什么

  • • 直接跑 prettier --write / black / gofmt -w 自动修复格式问题
  • • 命名不规范手动改,顺便确认语义是否清晰
  • • 缺注释的公共接口补上:做什么、参数含义、返回值、副作用

第五关:依赖与构建产物检查 —— 拦住「本地跑通,CI 挂了」的坑

做什么:确认 lockfile 变更合理、构建产物无异常、无多余文件提交。

为什么:AI 容易随手加依赖、改包版本、甚至生成不需要的文件(调试脚本、临时文件、巨大二进制)。这些上 CI 才发现,浪费时间。

命令示例

# 检查 lockfile 变更
git diff package-lock.json      # npm
git diff uv.lock / poetry.lock  # Python (uv/poetry)
git diff go.sum                 # Go

# 构建验证

npm run build                   # 前端
python -m build                 # Python 包
go build ./...                  # Go

# 检查暂存区有无异常文件

git status --porcelain | grep -E '^\?\?'  # 未跟踪文件
git diff --cached --name-only | xargs file | grep -v text  # 二进制文件

预期结果

  • lockfile 变更仅包含必要的新增/升级依赖,无无关版本抖动
  • • 构建成功,产物体积无异常膨胀
  • • 暂存区无调试脚本、.DS_Store、巨大二进制、本地配置文件

出错先查什么

  • • 多余依赖:确认是否真需要,不需要则 revert
  • • 版本抖动:锁定到兼容版本,避免 ^ / ~ 导致 CI 不稳定
  • • 异常文件:git reset HEAD <file> 移出暂存区,加入 .gitignore

常见问题

Q1:这 5 关跑下来要多久?会不会太慢?

A:配合缓存和增量检查,典型中型项目 2-5 分钟。建议接入 lefthookpre-commit 做本地预检,只在提交时跑轻量版(lint + 类型检查 + 单测),推送到 CI 再跑全量版(含安全扫描、构建验证)。

Q2:AI 生成的测试代码自己也可能有 bug,怎么办?

A:把「测试代码也要过 lint 和类型检查」加入第一关。核心逻辑测试建议人工复核断言逻辑,边界条件测试让 AI 生成后人工补全。

Q3:安全扫描误报太多,每次都要人工看不现实。

A:建立团队级 semgrep 规则集 / bandit 基线文件,把已确认的误报加入忽略列表。新代码只看新增的报警,存量不处理。

Q4:覆盖率达标但核心逻辑还是有 bug?

A:覆盖率是必要不充分条件。关键业务逻辑必须补充变异测试(如 stryker / mutmut / go-mutesting)或关键路径人工 Review。这 5 关是「最小可执行」,不是「唯一」。

Q5:项目没配这些工具,从零搭太麻烦?

A:从「 lint + 类型检查 + 单测」三件套起步,半天能跑通。安全扫描和变异测试后续补上。哪怕只有前三关,也能拦住 80% 以上的 AI 代码低级问题。


总结

这 5 道关的核心思想:把「靠经验、靠运气、靠仔细看」变成「靠工具、靠清单、靠自动化」

       
                                           
关卡核心工具拦住什么建议执行时机
1. 静态+类型eslint/ruff/golangci-lint + tsc/mypy/go vet语法错、类型错、弃用 API本地 pre-commit / CI
2. 测试+覆盖率jest/pytest/go test + coverage逻辑漏洞、边界未测本地 pre-push / CI
3. 安全扫描semgrep/bandit/gosec + audit注入、遍历、硬编码、CVECI(每夜/每推送)
4. 风格规范prettier/black/gofmt + 自定义规则命名混乱、注释缺失、模式不统一本地 pre-commit / CI
5. 依赖构建lockfile diff + build 验证多余依赖、版本抖动、异常文件本地 pre-push / CI
       
     

下一步能做什么

  • • 把这 5 关写成项目的 CONTRIBUTING.mdAI_CODING_CHECKLIST.md
  • • 接入 lefthook 自动化本地拦截
  • • 在 CI 里把安全扫描和覆盖率设为合并门禁
  • • 团队内做一次 15 分钟分享,统一执行标准

这篇教程属于「工具实战 / 上手教程」栏目。下一期预告:如何让 AI 编码助手生成的测试代码也靠谱——一套测试代码自检清单。