研发协作
当需要对 UI 改动做对抗性浏览器测试、QA PR…
适用于在真实浏览器中对抗性测试 UI 改动、QA PR、无障碍、响应式和探索性 bug,并输出证据化报告。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 59/100 ×0.15
适用场景
当需要对 UI 改动做对抗性浏览器测试、特定
解决思路
- 主 agent 负责协调:规划测试策略、委托给子 agent、合并结果;子 agent 执行实际浏览器测试。
- 在启动任何子 agent 前,主 agent 必须自己完成并输出三轮规划,不得委托给子 agent,不得跳到执行。
- Round 1 功能:列出核心用户流程和应能工作的点,每个测试写成「动作 → 预期结果」。
- Round 2 对抗:重读 Round 1,考虑不同用户类型/角色、错误路径、空状态、竞态条件、边界输入(空、巨大、特殊字符、快速点击)。
- Round 3 覆盖缺口:重读 Round 1-2,考虑无障碍(axe-core、仅键盘)、移动视口、控制台错误、与 app 其余部分的视觉一致性。
- 去重:合并三轮为一个编号测试列表,删除重叠,分配每个测试到组(如 Group A、Group B)。
- 执行一次:每组启动一个子 agent;每个子 agent 只收到具体测试列表,不探索或规划;子 agent 执行分配测试并报告结果。
- 在调用任何 Agent 工具前,在响应中输出三轮、合并计划、组分配。
- 子 agent 只运行分配的测试,不开放式探索;主 agent 给每个子 agent 具体编号测试列表;子 agent 不计划、不探索、不决定测什么,执行完停止。
- 拆分工作时注意瓶颈是最慢 agent,避免单一 agent 份额过大;许多小 agent 优于少数大 agent。
- 根据改动规模调整投入:单组件修复不需要很多 agent 或步骤;整页重设计需要更多;让 diff 范围驱动计划。
- 失败不提前停止:在分配测试内尽可能找更多 bug。
- 主 agent 必须在每个子 agent prompt 中包含明确的 browse step 限制,因为子 agent 不会自我限制。
- 步数启发:~25 步用于少量目标检查,~40 用于完整页面功能+对抗+a11y,~75 用于多页面或广泛类别;根据分配测试实际需要调整。
- 每个子 agent prompt 必须包含指定块:预算 N browse steps,计数,达到 N 立即停止并报告 STEP_PASS/STEP_FAIL,对未完成测试报告 STEP_SKIP|<test-id>|budget reached,不重试或继续,只运行指定测试,不探索,不生成 HTML 报告或写文件,只返回 step markers 和文本发现。
- 主 agent 自己不应运行 browse 命令(除了验证 dev server 已启动);所有测试在子 agent 中进行。
- 当子 agent 达到预算,主 agent 接受部分结果,不重跑或重试;最终报告包含 SKIPPED 测试。
- 每个子 agent 用指定格式报告:Tests: X | Passed: X | Failed: X | Skipped: X | Pages visited: X。
- 主 agent 合并最终报告格式:Tests: X | Passed: X | Failed: X | Skipped: X | Agents: X | Pass rate: X%。
- 不要报告 steps used。
- 作为对抗测试者:目标是找 bug,不是证明正确。
- 尝试破坏每个功能:点击两次、提交空表单、粘贴 500 字符、流程中按 Escape。
- 测试开发者没想到的:空状态、错误恢复、仅键盘导航、移动溢出。
- 每个断言必须基于证据:比较前后快照,按 ref 检查特定元素;没有具体证据不报告 PASS。
- 报告失败时包含可复现细节:确切动作、预期、实际、建议修复。
- 每个测试步骤必须产生结构化断言,不要写自由形式「看起来不错」。
- 每个测试步骤发出一个 marker:STEP_PASS|<step-id>|<evidence> 或 STEP_FAIL|<step-id>|<expected> → <actual>|<screenshot-path>。
- step-id 用短标识,如 homepage-cta、form-validation-error、modal-cancel。
- evidence 写观察到什么证明通过(元素 ref、文本内容、URL、eval 结果)。
- expected → actual 写预期与实际。
- screenshot-path 写保存截图路径(仅失败)。
- 每个 STEP_FAIL 必须有伴随截图,让开发者看到错误。
- 失败时立即截图:browse screenshot --path .context/ui-test-screenshots/<step-id>.png;如果 --path 不支持,browse screenshot 然后复制输出路径到该目录。
- 测试运行开始时设置截图目录:mkdir -p .context/ui-test-screenshots。
- 截图规则:文件名=step-id;存储在 .context/ui-test-screenshots/;并行运行包含 session 名:<session>-<step-id>.png;在失败瞬间截图;视觉/布局 bug 也截 baseline:<step-id>-baseline.png。
- 验证按严格程度排序:1) 确定性检查(browse eval 返回结构化数据),2) 快照元素匹配(特定 role/text 元素存在,按 ref),3) 前后比较(动作前后快照,验证树变化),4) 截图+视觉判断(仅视觉属性,最弱,需说明具体评估什么)。
- 每个交互使用前后比较模式:browse snapshot 捕获 BEFORE;执行交互(如 browse click @0-12);browse snapshot 捕获 AFTER;比较变化;发出 marker。
- 安装 browse:which browse || npm install -g browse。
- 避免权限疲劳:将 Bash(browse:*) 和 Bash(BROWSE_SESSION=*) 添加到 .claude/settings.json(项目级)或 ~/.claude/settings.json(用户级)的 permissions.allow。
- 模式选择:localhost/127.0.0.1 用本地模式 browse open <url> --local;部署/暂存站点用远程模式 browse open <url> --remote,需要 Browserbase 凭证;若 URL 含 localhost 或 127.0.0.1,首次 browse open 必须传 --local。
- 本地模式默认使用干净隔离的本地浏览器,适合可复现的 localhost QA。
- 仅当测试明确需要现有本地登录/cookies/状态时,使用 browse open <url> --auto-connect。
- 需要附加特定 CDP 目标时,使用 browse open <url> --cdp <port|url>。
- 远程模式:先运行 node .claude/skills/cookie-sync/scripts/cookie-sync.mjs --domains your-app.com 同步 cookies 到 Browserbase,获得 Context ID: ctx_abc123。
- 远程模式:用 SESSION_JSON="$(browse cloud sessions create --context-id ctx_abc123 --persist --keep-alive)",然后解析 SESSION_ID 和 CONNECT_URL。
- 远程模式:browse open https://staging.your-app.com --cdp "$CONNECT_URL",browse snapshot,运行测试,browse stop,browse cloud sessions update "$SESSION_ID" --status REQUEST_RELEASE。
- cookie-sync 标志:--domains、--context、--verified、--proxy "City,ST,US"。
- Workflow A 阶段1:分析 diff:git diff --name-only HEAD~1 或 git diff --name-only / git diff --name-only main...HEAD;git diff HEAD~1 -- <file> 读实际改动。
- 分类改动文件:*.tsx/*.jsx/*.vue/*.svelte 组件→测渲染、交互、状态、边界;pages/**、app/**、src/routes/** 路由→测导航、页面加载、内容、404;*.css/*.scss/*.module.css 样式→测视觉(截图)、响应式;*form*/*input*/*field* 表单→测验证、提交、空输入、长输入、特殊字符;*modal*/*dialog*/*dropdown* 交互→测打开/关闭、Escape、焦点陷阱、取消 vs 确认;*nav*/*menu*/*header* 导航→测链接、活动状态、路由、键盘导航;仅非 UI 文件→跳过,报告 no UI tests needed。
- Workflow A 阶段2:检测框架:cat package.json | grep -E '"(next|react|vue|nuxt|svelte|@sveltejs|angular|vite)"'。
- 映射文件到 URL:Next.js App Router 默认 3000,app/dashboard/page.tsx → /dashboard;Next.js Pages Router 3000,pages/about.tsx → /about;Vite 5173,检查 router config;Nuxt 3000,pages/index.vue → /;SvelteKit 5173,src/routes/+page.svelte → /;Angular 4200,检查 routing module。
- Workflow A 阶段3:测试前验证 dev server 服务的是 diff 代码,不是陈旧分支。
- 如果测试 PR 或特定分支:git branch --show-current 检查当前分支;若不是 PR 分支,git fetch origin <branch> && git checkout <branch>;yarn install 或 npm install / pnpm install 安装依赖;如果 dev server 已在其他分支运行,切换后重启。
- 查找运行中的 dev server:for port in 3000 3001 5173 4200 8080 8000 5000; do curl -s -o /dev/null -w "%{http_code}" "http://localhost:$port"; done,打印非 000 的端口。
- 如果没找到 dev server:告诉用户启动。
- 验证实际渲染:browse open + browse snapshot 后检查 a11y 树包含真实页面内容(导航、标题、交互元素),不是错误覆盖层或空 body;如果快照为空或被错误对话框主导,修复构建后再测试。
- Workflow A 阶段4:为每个改动区域规划 happy path 和对抗测试;示例测试计划包括有效邮箱提交、无效邮箱、空表单、XSS、快速双击、仅键盘流程。
- Workflow A 阶段5:执行测试:browse stop 2>/dev/null;mkdir -p .context/ui-test-screenshots;browse open http://localhost:3000 --local。
- 每个测试按 before/after pattern:browse open http://localhost:3000/path --local;browse wait load;browse snapshot 捕获 BEFORE;执行动作(browse click @0-ref / browse fill "selector" "value" / browse type "text" / browse press Enter);browse snapshot 捕获 AFTER;比较;发 marker。
- Workflow A 阶段6:报告结果格式:## UI Test Results,每个 STEP_PASS 和 STEP_FAIL 带 URL、Before、Action、After、Screenshot(失败)、Suggestion(失败);Summary: X/Y passed, Z failed;Failed: 列表;Screenshots saved to .context/ui-test-screenshots/。
- 完成后总是 browse stop。
- Workflow A 阶段7:生成 HTML 报告:读 references/report-template.html;替换占位符 {{TITLE}}、{{TITLE_HTML}}、{{META}}、{{TOTAL_TESTS}}、{{AGENT_COUNT}}、{{PASS_COUNT}}、{{FAIL_COUNT}}、{{PASS_RATE}}、{{RATE_CLASS}}、{{FAILURES_SECTION}}、{{PASSES_SECTION}}。
- 为每个测试结果生成 <details> 卡片:失败卡片 open 默认,通过卡片折叠;失败卡片包含 URL、Action、Expected、Actual、suggestion、截图 img;通过卡片包含 URL、Evidence。
- 嵌入截图为 base64:base64 -i .context/ui-test-screenshots/step-id.png | tr -d '\n',作为 src="data:image/png;base64,<output>";只对 STEP_PASS 显式截图的嵌入。
- 写最终 HTML 到 .context/ui-test-report.html:cat > .context/ui-test-report.html << 'REPORT_EOF' ... REPORT_EOF;用 open 或 xdg-open 打开;告诉用户 Report saved to .context/ui-test-report.html 并提供打开。
- HTML 报告规则:失败部分在通过之前;失败卡片默认 open,通过卡片折叠;每个 STEP_FAIL 卡片必须嵌入截图,若缺失则注明;包含建议修复;报告离线工作,无 CDN/外部资源;HTML 保持在 5MB 以下,若超出降低图片质量或跳过通过项的 baseline 截图。
- 对每个交互元素应用对抗测试模式;读 references/adversarial-patterns.md 获取完整模式库(表单、模态、导航、错误状态、键盘无障碍)。
- 确定性检查:axe-core 捕获 WCAG 违规,断言 violations.length === 0;Console errors 捕获运行时异常、失败请求,断言错误数组为空;Broken images 捕获缺失/失败图片加载,断言没有 naturalWidth === 0 的图片;Form labels 捕获没有可访问标签的输入,断言每个 input 都有 hasLabel: true。读 references/browser-recipes.md 获取确切 browse eval 配方。
- Workflow B 探索性测试:无 diff、无计划,打开应用尝试破坏。步骤:读 package.json 检测框架,打开根 URL 并快照;点击导航链接,访问每个可达页面,记录存在内容;对每个页面应用对抗模式;运行确定性检查(axe-core、console errors、broken images、form labels);报告发现,使用 STEP_PASS/STEP_FAIL marker,包含复现步骤。
- 探索提示:从首页开始,自然跟随导航;试 404 页 /does-not-exist,看是否自定义;找空状态;先用垃圾输入测试表单再有效输入;每页检查移动视口 375px 是否溢出;如果 app 有 auth,先用 cookie-sync。
- Workflow C 并行测试:用命名 browse 会话 BROWSE_SESSION=<name> 并发运行独立测试组;每个会话有自己的浏览器;支持本地和远程;用于多页面或类别以加快墙钟时间;读 references/parallel-testing.md 获取完整工作流:会话设置、agent fan-out、认证 cookie-sync、结果合并。
- 设计一致性:检查改动 UI 是否与应用其余部分视觉匹配;读 references/design-consistency.md 进行视觉或设计检查。
- 测试类别:无障碍(axe-core + 键盘导航,确定性违规数);视觉质量(截图+启发式评估,视觉判断,说明具体点);响应式(视口扫描+截图,视觉+确定性溢出检查);控制台健康(控制台捕获 eval,确定性错误数);UX 启发式(快照+Laws of UX+Nielsen's,结构化判断,引用具体启发式);错误状态(导航到空/错误状态,前后比较);数据展示(表格/仪表盘快照,元素匹配列数、格式);设计一致性(截图 baseline+改动页比较,视觉判断,引用具体属性);探索性(自由导航+对抗测试,前后+判断)。
- 按需加载参考指南:adversarial-patterns.md 测试表单、模态、导航、键盘 a11y 时;browser-recipes.md 运行确定性检查时;exploratory-testing.md Workflow B;ux-heuristics.md 评估 UX 质量或引用启发式时;design-system.example.md 用户自定义模板;design-consistency.md 视觉一致性检查;parallel-testing.md Workflow C;report-template.html Phase 7。
- 需要看断言协议实际操作的完整示例时读 EXAMPLES.md。
- 最佳实践:对抗性;每个断言需要证据;每个交互前后快照;每个失败截图;确定性检查优先;localhost 从干净本地模式开始,首次 browse open 传 --local,仅当需要现有本地状态时用 --auto-connect;完成后总是 browse stop,并行运行停止每个命名会话;失败报告带复现步骤、截图路径、建议;独立测试并行化,Workflow C 命名会话。
- 故障排除:No active page → browse stop 重试,僵尸进程 pkill -f "browse.*daemon";Dev server 无响应 → curl http://localhost:<port>,让用户启动;browse eval 带 await 失败 → 用 .then(),不支持 top-level await;Element ref 找不到 → 重新 browse snapshot,refs 页面更新会变;Blank snapshot → browse wait load 或 browse wait selector ".expected" 再快照;SPA 深链 404 → 先导航到 /,再点击;远程 auth 失败 → 重新 cookie-sync 带 --context <id>,试 --verified;并行会话冲突 → 确保每个 browse 命令用 BROWSE_SESSION=<name>,否则去默认会话;会话不停止 → BROWSE_SESSION=<name> browse stop,僵尸进程 pkill -f "browse.*<name>.*daemon"。
适用边界 · 注意事项
- 不适用于纯后端或非 UI 代码改动,或没有可访问的 dev server 时。
- 不适用于未安装 browse CLI 或无法运行本地浏览器的环境。
- 不适用于需要远程认证但缺少 Browserbase 凭证和 cookie-sync 时。