从一次 code review 说起
上个月改了个通讯录权限管理的需求------在不可见规则里加公共联系人支持。代码改完了,功能写好了,提交给 QA 之前想自己先跑一下。本地开了 npm run start,手动点页面、开弹窗、看 tab 有没有出来、保存会不会报错。
搞了 10 分钟就觉得烦------每次改代码都得重复这些操作。脑子里冒出一个念头:能不能让 AI 帮我在浏览器里跑一遍?
需求很直接:给 AI 一段 git diff,让它自动找到改了哪个页面、打开浏览器、按照需求描述点一遍流程、截图给我看结果。
说干就干。
AI 问了 7 个问题
一开始我只是给了句模糊的话:"从产品需求出发,开发完以后通过 diff 代码和 kimi webbridge 完成自动化测试。" AI 没有直接写代码,而是启动了 brainstorming 流程,开始逐轮追问。
第 1 问:这是给 AI agent 用的工具,还是给人类用的 CLI?
我说 AI agent 用的。
第 2 问:核心价值是什么------自动理解 diff 变更然后去浏览器验证?
我说测试用例 + 代码 diff → 浏览器验证。
第 3 问:测试用例从哪来、什么格式?
我说 QA 同学以 md 文件提供,沿用他们现有格式。
第 4 问:在同一个对话里验证,还是新开一个对话?
我说新开一个,最好做成 skill。
第 5 问:测试用例 md 用什么格式------自然语言还是结构化表格?
我说沿 QA 现有格式,不给他们加活。
第 6 问:三个方案选一个------全自动解析、引导式交互、模板驱动?
我选了全自动(方案 A),AI 从 diff 和用例里自己推导测试场景。
第 7 问:除了核心流程,还要不要自动路由发现、页面就绪检测、console 错误收集?
我全要。
这 7 个问题走完,需求边界就清楚了。AI 输出了一份设计文档,然后我们逐节确认------工作流、路由发现、就绪检测、报告格式,一层一层过。全部确认后才开始写代码。
体感是:虽然全程跟 AI 对话,但节奏很像跟一个 senior engineer 做技术方案评审------他追问细节,我拍板决策,然后他出设计稿。
三个关键设计决策
整个 skill 的核心逻辑就三步:从 diff 推导页面 URL → 打开浏览器 → 按场景执行操作。但每一步都有值得聊的设计点。
1. 路由推导:怎么从 diff 找到要测哪个页面
这个 skill 是项目无关的,不能硬编码任何路由映射。用了 5 级策略逐级降级:
策略1: 路由配置文件 --- 搜索 diff 中的 routes.ts、app-routing.module.ts 等
策略2: 路由跳转代码 --- router.push(...)、$state.go(...)、<Link to=...
策略3: 文件路径反推 --- pages/xxx/ → /xxx
策略4: API endpoint 逆推 --- /xhr/xxx → 找到引用它的页面
策略5: 问用户
实际效果:第一个版本硬编码了一份路由映射表,后来重构时改成了这 5 级通用策略。React / Vue / Angular 项目都能覆盖。
2. 页面就绪检测:什么时候才算"加载完了"
这是最容易被忽略的问题。直接 navigate 后立刻截图,大概率拍到白屏。
用了 4 级策略:
策略1(首选): 快照对比 --- 连续 2 次 snapshot,间隔 1s,DOM 树完全一致 = 渲染稳定
策略2: loading 关键词 --- snapshot 中无 "loading"、progressbar 等
策略3: 预期文本匹配 --- 从测试场景提取关键文本,搜到即就绪
策略4: 8 秒兜底
关键洞察:快照对比是唯一真正项目无关的方式。不管用了 React、Vue 还是 Angular,最终都是 DOM 稳定。不需要知道用了什么 loading 组件、什么 class 名。
3. 为什么做成 skill 而不是脚本
skill 和脚本的本质区别:
- 脚本是死的,只能执行预设步骤
- skill 是活的,AI 加载后能理解自然语言输入、推导测试场景、灵活调整
举个例子:用户说"帮我验证 HEAD 这次改动",skill 会自动跑 git diff、推导 URL、生成测试计划、打开浏览器执行。脚本做不到这些,因为脚本不知道"这次改动"是什么。
同时 skill 的输出是 Markdown 报告,而不是一个 pass/fail 的布尔值。每个场景有截图、console 错误、网络异常,人能看、AI 也能继续分析。
编码踩坑
前面说得挺顺,但写代码的时候也踩了几个坑。说两个印象最深的。
坑 1:Python 写入被覆盖
项目的 AGENTS.md 里有个规则:git 已追踪的文件不能用 OpenCode 的 Edit/Write 工具(会触发 Prettier 格式化污染整个文件),必须用 Python 直写。
我写了三段 Python 脚本按顺序改同一个文件------第一段改 imports 和 DEFAULT_FORM,第二段改 useEffect 和 selectHiddenAccounts,第三段改 JSX。结果第二段读文件时第一段的改动没生效,第三段又把前两段覆盖了。折腾半天才发现 Python 的 write 每次都是全量覆写,不是追加。最后把所有改动合到一个脚本里重来一遍。
坑 2:\n 转义地狱
Skill 文件里需要嵌入 bash 代码块,代码块里又有 JSON 字符串。Python 的 -c 模式下,单双引号和反斜杠的转义层数直接把人逼疯。最后改用 python3 << 'PYEOF' heredoc,单引号阻止 shell 层面转义,才算消停。
怎么用
安装就是一句话:
bash
git clone https://github.com/wj100/skills.git ~/.opencode/skills
然后在 OpenCode 里直接说:
帮我验证 HEAD 这次改动
或者带需求/用例:
帮我验证 feature/xxx 对 dev 的改动
需求: doc/需求.md
用例: doc/测试用例.md
Skill 会自动加载,四步走完输出报告:
# 测试报告 --- 通讯录不可见规则支持公共联系人
## 变更摘要
- diff 范围:dev..feature/xxx
- 改动文件:4 个
- 测试页面:http://localhost:3000/#/address/contactsVisibility
## 测试结果
| # | 优先级 | 场景 | 状态 | 截图 |
|---|--------|------|------|------|
| 1 | P0 | 创建规则页面正常加载 | ✅ | /tmp/e2e-test/... |
| 2 | P0 | 选择成员弹窗含两个 tab | ✅ | /tmp/e2e-test/... |
## Console 异常
(无)
## 网络异常
(无)
小结
这个 skill 从想法到能用,前前后后大概花了半天。复盘几个感受:
-
AI 做技术评审是靠谱的。brainstorming 阶段的 7 个追问确实帮我把模糊想法变成了清晰设计。这个环节如果自己闷头想,大概率会漏掉关键决策点------比如"要不要自动路由发现"、"测试用例不来的时候怎么办"。
-
快照对比是通用兜底方案。做项目无关工具时,优先找"所有项目都一样的底层特性"------DOM 树、HTTP 请求、git diff 格式------而不是绑定特定框架的 class 名或生命周期。
-
skill 比脚本更适合 AI agent 场景。因为它不是机械执行,而是能理解自然语言输入、推理测试场景、灵活调整策略。后续可以加的功能:对接 CI 自动触发、多页面端到端流程测试、失败场景自动重试。