如何给不确定的AI写测试?claude-code-from-scratch 22项功能测试与mock模型实战指南
【免费下载链接】claude-code-from-scratchBuild your own Claude Code from scratch. 🔍 Claude Code 开源了 50 万行代码,读不动?用 ~5000 行 TypeScript / Python 从零复现核心架构,11 章分步教程带你理解 coding agent 精髓项目地址: https://gitcode.com/gh_mirrors/cl/claude-code-from-scratch
给 AI 写测试,最大的难点在于模型输出"这次是这样、下次可能那样"。本文以开源项目 claude-code-from-scratch 为例——它用约 5000 行 TypeScript / Python 代码从零复现了 Claude Code 的核心架构,带你完整跑一遍覆盖全部功能的 22 项功能测试,并学会用一个本地 mock 模型,搭出一条全程离线、可重复执行的端到端测试流水线,是一份面向初学者的 coding agent 测试实战指南。
为什么"不确定"的 AI 需要专门的测试方法
普通软件的功能行为是确定的,而 coding agent 的核心行为取决于 LLM 每一轮的响应:
- 模型是否选对了工具?
- 并行工具执行真的是并行的吗?
- 语义记忆召回的时机对不对?
- Plan Mode 的审批流程是否流畅?
单元测试只能覆盖确定性的工具函数(文件读写、权限检查),但端到端的 agent 行为单靠单测兜不住。因此这个项目采用了双轨测试策略:手动 22 项场景验收 + 本地 mock 模型的自动化集成测试,两者互补而不互相替代。
| 测试层 | 方式 | 覆盖什么 |
|---|---|---|
| 手动场景 | 22 项功能测试清单 | 真实模型的判断力与交互手感 |
| 自动化集成测试 | 本地 mock 模型 + 真 CLI | 循环接线、权限、流式、MCP |
| 真模型冒烟(可选) | 连真实 API | 发现 mock 与真实 API 的"协议漂移" |
下面两层完全离线、不用 API key,随时可跑。完整说明见官方文档:docs/14-testing.md。
测试环境准备:两条命令完成
先克隆项目并安装依赖(TS 版需要构建,Python 版无需构建):
git clone https://gitcode.com/gh_mirrors/cl/claude-code-from-scratch.git cd claude-code-from-scratch npm install && npm run build再一键配置测试环境:test/setup.sh 会自动配好 MCP 服务器、skills、CLAUDE.md规则、大文件和自定义 agent;测完后用 test/cleanup.sh 清理全部临时文件。
💡 TypeScript 与 Python 两个版本功能完全一致,测试时把
node dist/cli.js换成python -m mini_claude即可。
22 项功能测试:从基础工具到自治续跑的 8 个阶段
完整清单在 docs/14-testing.md,按 8 个阶段组织,结构如下:
| 阶段 | 测试项 | 覆盖功能 |
|---|---|---|
| ① 基础工具 | 1–3 | MCP 工具调用、WebFetch、并行工具执行 |
| ② 记忆与上下文 | 4–7 | 语义记忆召回、@include 规则、Read-before-edit、大结果持久化 |
| ③ 技能与扩展 | 8–10 | Skill 调用、ToolSearch 延迟加载、REPL 命令 |
| ④ Agent 架构 | 11–12 | Sub-agent 系统、Plan Mode 审批流 |
| ⑤ 编辑与搜索 | 13、17–18 | 引号规范化、Grep 搜索、文件写入 |
| ⑥ 会话与 CLI | 14–16 | 会话恢复、one-shot 模式、预算控制 |
| ⑦ 扩展系统 | 19 | 自定义 Agent |
| ⑧ 自治续跑 | 20–22 | /goal 回灌、/loop 双节奏、Auto Mode 拦截 |
其中两项最值得体验:
- 语义记忆召回(Test 4):先在一个对话里保存 3 条记忆,退出后新开对话问一个语义相关的问题——模型应当"想起"部署地址、截止时间等细节。这一项验证了异步 prefetch 召回的完整链路,也是 AI 产品"记性"的典型测法。
- Auto Mode 拦截(Test 22):用
--auto启动,先跑只读任务(应直接放行),再让它执行git push origin main——安全分类器应命中规则并拦截危险操作。设计细节可读 docs/15-autonomy.md。
动手前还可以对照速查清单逐项打勾:test/TEST-GUIDE.md。
mock 模型实战:给 LLM 写一份"剧本"
自动化集成测试的关键,是把"不确定"变成"剧本"。
mock 模型 mock-llm.mjs 是一个本地 HTTP 服务,同时实现了 OpenAI 与 Anthropic 两套接口的协议。你写一份 JSON 场景脚本,它就按剧本"演"模型:
{ "main": [{ "tool_calls": [{ "name": "read_file", "arguments": { "file_path": "README.md" } }] }], "evaluator": ["{\"ok\":true,\"reason\":\"done\"}"] }有三个细节值得留意:
- 请求分类路由:主对话循环走流式请求(
main队列);/goal 评估器、安全分类器等旁路查询走非流式请求,各配独立队列、互不干扰。 - 故障注入:通过
status队列可让每次主请求返回 429、500 等状态码,重试逻辑由此也能被确定性验证。 - 防"假绿":如果 CLI 发出了超出剧本的请求,测试框架 harness.mjs 会直接报错;断言还会核对"回传给模型的真实工具输出"和"磁盘上的实际文件内容",避免"剧本恰好撞上正确答案"的假通过。
每个用例还运行在一次性沙箱里:临时 HOME + 临时工作目录(可选 git init),既不污染也不被污染真实的~/.claude,跑完即清理。几个代表性测试示例:
- tool-chain.test.mjs:read → edit → read-back 多轮工具链,验证编辑真的落盘
- goal-loop.test.mjs:/goal 达成、未达成回灌、判定不可能时刹车
- confirm.test.mjs:turn 中途权限确认框里回答 y / n 的两条路径
如何跑完全部测试:两条命令
npm run check:full # TS/Python 单元 + 双后端集成测试(mock,离线) npm run test:live # 真模型冒烟:.env 配了 key 才跑,没配自动跳过check:full会把同一份场景脚本分别在 OpenAI 与 Anthropic 两个后端、TS 与 Python 两个实现上各跑一遍——全程不联网、不用 key。test:live则专抓 mock 与真实 API 之间的"协议漂移":一旦真模型跑挂而 mock 全绿,就是该更新协议假设的信号。
总结:AI 项目的三层测试金字塔
| 层 | 位置 | 作用 |
|---|---|---|
| 单元测试 | src/ 与 python/mini_claude/ 配套 | 确定性函数 |
| mock 集成测试 | test/integration/ | 端到端行为,离线可重复 |
| 真模型冒烟 | npm run test:live | 捕捉协议漂移 |
核心思路一句话:确定性的部分用单测,不确定的部分用 mock 剧本化,真模型只留作最后一道关。这套三层方法不只属于这个项目——任何接入了 LLM 的应用,都可以照此搭建自己的测试体系。
【免费下载链接】claude-code-from-scratchBuild your own Claude Code from scratch. 🔍 Claude Code 开源了 50 万行代码,读不动?用 ~5000 行 TypeScript / Python 从零复现核心架构,11 章分步教程带你理解 coding agent 精髓项目地址: https://gitcode.com/gh_mirrors/cl/claude-code-from-scratch
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考