mcpField
U
ui-test

ui-test

github.com/browserbase测试与质量3.7k3.0k 次安装8 周前更新
代码仓库

关于 ui-test

ui-test 是用于在真实浏览器中对 UI 变更进行对抗式测试的 Agent 技能。它支持基于 diff、探索式和并行测试,由子 Agent 执行分配的检查并提交有证据的结果。

主要功能

  1. 01基于 diff 的 UI 测试
  2. 02探索式浏览器测试
  3. 03子 Agent 并行分组测试
  4. 04结构化断言与失败截图
  5. 05功能、边缘情况和无障碍检查

适用场景

  1. 01验证 git diff 中的 UI 变更
  2. 02探查表单和流程的边缘故障
  3. 03在多个浏览器分派独立测试
  4. 04提交带证据的可复现故障报告

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/browserbase/skills --skill ui-test

安装后在 Claude Code 中输入/ui-test确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

EXAMPLES.md
LICENSE.txt
README.md
references/
adversarial-patterns.md
browser-recipes.md
design-consistency.md
design-system.example.md
exploratory-testing.md
parallel-testing.md
report-template.html
ux-heuristics.md

详细介绍

UI Test — Agentic UI Testing Skill

在真实浏览器中测试 UI 变更。你的任务是尝试找出问题,而不是确认功能正常。

三种工作流:

  • 差异驱动 — 分析 git diff,只测试发生变更的部分
  • 探索式 — 浏览应用,找出开发者未曾想到的错误
  • 并行 — 将独立的测试组分配到多个 Browserbase 浏览器并行执行

测试如何进行

主 Agent 负责协调——制定测试策略、将任务分配给子 Agent,并汇总结果。子 Agent 负责实际的浏览器测试。

规划:从多个角度分析,然后一次性执行

在启动任何子 Agent 之前,你必须亲自完成全部三轮规划并输出结果。 规划应在你自己的回复中完成,不能委托给子 Agent。不要跳过规划直接开始执行。

第 1 轮——功能: 核心用户流程有哪些?哪些功能应该正常运行?按以下格式写出每项测试:操作 → 预期结果。

第 2 轮——对抗性测试: 重新阅读第 1 轮。遗漏了什么?考虑以下方面:不同用户类型/角色、错误路径、空状态、竞态条件、边界输入(空值、超大输入、特殊字符、快速点击)。

第 3 轮——覆盖缺口: 重新阅读第 1–2 轮。还要考虑哪些方面?无障碍(axe-core、仅用键盘操作)、移动端视口、控制台错误、与应用其他部分的视觉一致性。

去重: 将三轮内容合并成一份带编号的测试清单。删除重复项。为每项测试分配一个组(例如 Group A、Group B)。

然后一次性执行——每组启动一个子 Agent。每个子 Agent 只会收到分配给自己的具体测试清单,不会收到其他内容。子 Agent 不进行探索或规划,只执行分配的测试并报告结果。

调用任何 Agent 工具之前,先在回复中输出三轮规划、合并后的计划和分组分配。

拆分工作的原则
  • 子 Agent 执行分配的测试,不进行开放式探索。 主 Agent 将具体的编号测试清单交给每个子 Agent。子 Agent 不规划、不探索,也不自行决定测试内容,只执行清单并停止。
  • 瓶颈在于最慢的 Agent——拆分工作时,不要让任何单个 Agent 承担过多任务。多个小型 Agent 优于少数大型 Agent。
  • 根据变更规模安排工作量——单个组件的修复不需要很多 Agent 或很多步骤;整页重新设计则需要更多。让 diff 的范围决定计划。
  • 失败后不要提前停止——在分配的测试范围内尽可能多地找出问题。
为子 Agent 设置步骤预算

主 Agent 必须在每个子 Agent 提示词中明确规定浏览步骤上限。 子 Agent 不会自行限制;如果没有明确要求,它们会一直运行到完成为止。

粗略参考:少量针对性检查约 25 步;包含功能、对抗性和无障碍测试的完整页面约 40 步;多个页面或范围较广的类别约 75 步。根据分配的测试实际所需进行调整——这些只是起始参考,并非硬性规定。

粗略参考:少量针对性检查约 25 步;包含功能、对抗性和无障碍测试的完整页面约 40 步;多个页面或范围较广的类别约 75 步。根据分配的测试实际所需进行调整——这些只是起始参考,并非硬性规定。

每个子 Agent 的提示词都必须包含:

You have a budget of N browse steps (each `browse` command = 1 step). Count your steps as you go. When you reach N, stop immediately and report:
- STEP_PASS/STEP_FAIL for every test you completed
- STEP_SKIP|<test-id>|budget reached for every test you didn't get to

Do not retry or continue after hitting the budget.
Run only these tests: [numbered list from the merged plan]
Do not explore beyond the assigned tests.
Do NOT generate an HTML report or write any files. Return only step markers and your findings as text.

主 Agent 不应自行运行 browse 命令(验证开发服务器是否启动除外)。所有测试都由子 Agent 执行。

子 Agent 达到步骤预算时,主 Agent 应原样接受部分结果。 不要重新运行或重试该子 Agent。在最终报告中列出已跳过的测试,让开发者知道哪些测试未覆盖。

报告

每个子 Agent 都必须报告:

Tests: 8 | Passed: 5 | Failed: 2 | Skipped: 1 | Pages visited: 2

主 Agent 将结果汇总为最终报告,其中包括:

Tests: 20 | Passed: 14 | Failed: 4 | Skipped: 2 | Agents: 3 | Pass rate: 70%

不要报告“使用的步骤数”——浏览命令计数只是实现细节,对审核者来说并非有意义的指标。

测试理念

你是一个对抗性测试人员。 你的目标是找出 Bug,而不是证明功能正确。

  • 尝试破坏你测试的每项功能。 不要只检查“按钮是否存在?”——快速连续点击两次、提交空表单、粘贴 500 个字符、在流程进行中按 Escape。
  • 测试开发者没想到的情况。 空状态、错误恢复、仅使用键盘导航、移动设备上的溢出。
  • 每项断言都必须有证据支持。 比较操作前后的快照。通过 ref 检查特定元素。没有无障碍树或确定性检查提供的具体证据,绝不报告 PASS。
  • 报告失败时提供足够的复现细节。 包含确切操作、预期结果、实际结果,以及建议的修复方案。

断言协议

每个测试步骤都必须生成结构化断言。不要写自由形式的“看起来不错”。

步骤标记

对每个测试步骤,恰好输出一个标记:

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 都必须附带截图,让开发者能直观看到问题所在。

测试步骤失败时:

# 1. Take a screenshot immediately after observing the failure
browse screenshot --path .context/ui-test-screenshots/<step-id>.png

# If --path is not supported, take the screenshot and save manually:
browse screenshot
# The browse CLI will output the screenshot path — move/copy it:
cp /tmp/browse-screenshot-*.png .context/ui-test-screenshots/<step-id>.png

在每次测试运行开始时设置截图目录:

mkdir -p .context/ui-test-screenshots

规则:

  • 文件名 = step-id(例如,double-submit.png、axe-audit.png、modal-focus-trap.png)
  • 存放在 .context/ui-test-screenshots/ 中——此目录已加入 gitignore,开发者和其他 Agent 均可访问
  • 并行运行时,加入会话名称:<session>-<step-id>.png(例如,signup-double-submit.png)
  • 在失败发生时立即截图——捕获故障状态,而不是恢复后的状态
  • 对于视觉或布局 Bug,也要截取基线(正常状态)截图,以便比较:<step-id>-baseline.png
验证方式(按严谨程度排序)
  1. 确定性检查(最有力)——browse eval 返回可供检查的结构化数据。例如:axe-core 违规数量、document.title、表单字段值、控制台错误数组、元素数量。
  2. 快照元素匹配——无障碍树中存在具有特定角色和文本的特定元素。通过 ref 检查:@0-12 button "Save"。元素要么存在于树中,要么不存在。
  3. 操作前后比较——操作前获取快照,执行操作,再获取操作后的快照。确认树按预期发生变化(元素出现、消失或文本改变)。
  4. 截图 + 视觉判断(最弱)——仅用于无障碍树无法捕获的视觉属性(颜色、间距、布局)。务必说明具体评估内容。
操作前后比较模式

这是核心验证循环。每次交互都使用它:

# 1. BEFORE: capture state
browse snapshot
# Record: what elements exist, their text, their refs

# 2. ACT: perform the interaction
browse click @0-12

# 3. AFTER: capture new state
browse snapshot
# Compare: what changed? What appeared? What disappeared?

# 4. ASSERT: emit marker based on comparison
# If dialog appeared: STEP_PASS|modal-open|dialog "Confirm" appeared at @0-20
# If nothing changed:
browse screenshot --path .context/ui-test-screenshots/modal-open.png
# STEP_FAIL|modal-open|expected dialog to appear → snapshot unchanged|.context/ui-test-screenshots/modal-open.png

设置

which browse || npm install -g browse
避免权限疲劳

此技能会运行许多 browse 命令(快照、点击、eval)。为了避免每次都要批准,请将 browse 添加到允许的命令中:

将两种模式都添加到 .claude/settings.json(项目级)或 ~/.claude/settings.json(用户级):

{
  "permissions": {
    "allow": [
      "Bash(browse:*)",
      "Bash(BROWSE_SESSION=*)"
    ]
  }
}

第一种模式涵盖普通 browse 命令。第二种模式涵盖并行会话(BROWSE_SESSION=signup browse open ...)。两种模式都需要添加,才能避免出现批准提示。

模式选择

目标模式命令身份验证
localhost / 127.0.0.1本地browse open <url> --local无需认证(默认使用干净、隔离的本地浏览器)
已部署/预发布站点远程browse open <url> --remote需要 Browserbase 凭据;在支持的情况下使用上下文

规则:如果目标 URL 包含 localhost 或 127.0.0.1,首次运行 browse open 时必须传入 --local。

本地模式(默认用于 localhost)
browse open http://localhost:3000 --local

browse open ... --local 默认使用干净、隔离的本地浏览器,非常适合执行可复现的 localhost QA 测试。

仅在需要时使用本地模式变体:

  • browse open <url> --auto-connect — 自动发现现有的、可调试的本地 Chrome。仅当测试明确需要使用现有的本地登录状态、Cookie 或状态数据时使用。
  • browse open <url> --cdp <port|url> — 附加到指定的 CDP 目标(显式附加到本地浏览器)。
远程模式(通过 Cookie 同步访问已部署的网站)
# Step 1: Sync cookies from local Chrome to Browserbase
node .claude/skills/cookie-sync/scripts/cookie-sync.mjs --domains your-app.com
# Output: Context ID: ctx_abc123

# Step 2: Open in remote mode with the synced context
SESSION_JSON="$(browse cloud sessions create --context-id ctx_abc123 --persist --keep-alive)"
SESSION_ID="$(echo "$SESSION_JSON" | jq -r .id)"
CONNECT_URL="$(echo "$SESSION_JSON" | jq -r .connectUrl)"

browse open https://staging.your-app.com --cdp "$CONNECT_URL"
browse snapshot
# ... run tests ...
browse stop
browse cloud sessions update "$SESSION_ID" --status REQUEST_RELEASE

Cookie 同步标志:--domains、--context、--verified、--proxy "City,ST,US"

工作流 A:由差异驱动的测试

阶段 1:分析差异
git diff --name-only HEAD~1          # or: git diff --name-only / git diff --name-only main...HEAD
git diff HEAD~1 -- <file>            # read actual changes

对变更文件分类:

文件模式UI 影响测试内容
*.tsx、*.jsx、*.vue、*.svelte组件渲染、交互、状态、边界情况
pages/**、app/**、src/routes/**路由/页面导航、页面加载、内容、404 处理
*.css、*.scss、*.module.css样式视觉外观(截图)、响应式表现
*form*、*input*、*field*表单验证、提交、空输入、长输入、特殊字符
*modal*、*dialog*、*dropdown*交互打开/关闭、Escape 键、焦点陷阱、取消与确认
*nav*、*menu*、*header*导航链接、活动状态、路由、键盘导航
仅包含非 UI 文件无跳过 — 报告“无需进行 UI 测试”
阶段 2:将文件映射到 URL

检测框架:cat package.json | grep -E '"(next|react|vue|nuxt|svelte|@sveltejs|angular|vite)"'

框架默认端口文件 → URL 模式
Next.js App Router3000app/dashboard/page.tsx → /dashboard
Next.js Pages Router3000pages/about.tsx → /about
Vite5173检查路由器配置
Nuxt3000pages/index.vue → /
SvelteKit5173src/routes/+page.svelte → /
Angular4200检查路由模块
阶段 3:确保运行的是正确的代码

测试前,确认开发服务正在提供差异中的代码,而不是过期分支的代码。

如果测试 PR 或特定分支:

# Check what branch is currently checked out
git branch --show-current

# If it's not the PR branch, switch to it
git fetch origin <branch> && git checkout <branch>

# Install deps — the lockfile may differ between branches
yarn install  # or npm install / pnpm install

如果开发服务已在其他分支上运行,请在检出目标分支后重启服务。

查找正在运行的开发服务:

for port in 3000 3001 5173 4200 8080 8000 5000; do
  s=$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:$port" 2>/dev/null)
  if [ "$s" != "000" ]; then echo "Dev server on port $port (HTTP $s)"; fi
done

如果未找到任何服务:告知用户启动开发服务。

确认页面确实正常渲染: 执行 browse open 和 browse snapshot 后,检查无障碍树中是否包含真实页面内容(导航、标题、交互元素),而非只有错误覆盖层或空白正文。Next.js 开发服务可能返回 HTTP 200,但显示全屏构建错误对话框。如果快照为空或主要内容是错误对话框,则说明服务存在问题 — 测试前先修复构建问题。

阶段 4:生成测试计划

针对每个变更部分,同时规划正常路径和对抗性测试:

Test Plan (based on git diff)
=============================
Changed: src/components/SignupForm.tsx (added email validation)

1. [happy] Valid email submits successfully
   URL: http://localhost:3000/signup
   Steps: fill valid email → submit → verify success message appears

2. [adversarial] Invalid email shows error
   Steps: fill "not-an-email" → submit → verify error message appears

3. [adversarial] Empty form submission
   Steps: click submit without filling anything → verify error, no crash

4. [adversarial] XSS in email field
   Steps: fill "<script>alert(1)</script>" → submit → verify sanitized/rejected

5. [adversarial] Rapid double-submit
   Steps: click submit twice quickly → verify no duplicate submission

6. [adversarial] Keyboard-only flow
   Steps: Tab to email → type → Tab to submit → Enter → verify success
阶段 5:执行测试
browse stop 2>/dev/null
mkdir -p .context/ui-test-screenshots
# localhost/default QA → clean, reproducible local run
browse open http://localhost:3000 --local

每项测试都遵循前后对照模式:

# Navigate
browse open http://localhost:3000/path --local
browse wait load

# BEFORE snapshot
browse snapshot
# Note the current state: elements, refs, text

# ACT
browse click @0-ref
# or: browse fill "selector" "value"
# or: browse type "text"
# or: browse press Enter

# AFTER snapshot
browse snapshot
# Compare against BEFORE: what changed?

# ASSERT with marker
# STEP_PASS|step-id|evidence  OR  STEP_FAIL|step-id|expected → actual
阶段 6:报告结果
## UI Test Results

### STEP_PASS|valid-email-submit|status "Thanks!" appeared at @0-42 after submit
- URL: http://localhost:3000/signup
- Before: form with email input @0-3, submit button @0-7
- Action: filled "[email protected]", clicked @0-7
- After: form replaced by status element with "Thanks! We'll be in touch."

### STEP_FAIL|double-submit|expected single submission → form submitted twice|.context/ui-test-screenshots/double-submit.png
- URL: http://localhost:3000/signup
- Before: form with submit button @0-7
- Action: clicked @0-7 twice rapidly
- After: two success toasts appeared, suggesting duplicate submission
- Screenshot: .context/ui-test-screenshots/double-submit.png
- Suggestion: disable submit button after first click, or debounce the handler

---
**Summary: 4/6 passed, 2 failed**
Failed: double-submit, xss-sanitization

Screenshots saved to `.context/ui-test-screenshots/` — open any failed step's screenshot to see the broken state.

完成后务必执行 browse stop。

阶段 7:生成 HTML 报告

生成文本报告后,再生成一份独立的 HTML 报告,供审核者在浏览器中打开。报告会以内嵌的 Base64 格式包含截图,因此整个报告只需一个文件即可运行,无需外部依赖。

**原因:**文本报告适合 Agent 对话,但审核者(产品经理、设计师及其他工程师)需要一份可打开、浏览和分享的可视化材料。内嵌截图能让故障一目了然。

生成方式
  1. 阅读 HTML 模板 references/report-template.html
  2. 将实际测试数据填入模板占位符,生成报告:
占位符值
{{TITLE}}<title> 标签的报告标题(例如:“UI Test: PR #1234 — OAuth Settings”)
{{TITLE_HTML}}可见 <h1> 的报告标题。如果有 PR URL,请将 PR 引用包在 <a> 标签中,使其可点击(例如:UI Test: <a href="https://github.com/org/repo/pull/1234">PR #1234</a> — OAuth Settings)。如果没有 URL,则使用与 {{TITLE}} 相同的纯文本。
{{META}}单行上下文信息:日期、应用 URL、用户、分支
{{TOTAL_TESTS}}STEP_PASS + STEP_FAIL 的总数
{{AGENT_COUNT}}运行的子 Agent 数量
{{PASS_COUNT}}STEP_PASS 的数量
{{FAIL_COUNT}}STEP_FAIL 的数量
{{PASS_RATE}}整数百分比(例如:“92”)
{{RATE_CLASS}}good(≥90%)、warn(70–89%)、bad(<70%)
{{FAILURES_SECTION}}失败测试卡片的 HTML(见下文)
{{PASSES_SECTION}}通过测试卡片的 HTML(见下文)
  1. 为每个测试结果生成一个 <details> 卡片。失败测试应默认展开,以便审核者立即看到:

<div class="section">
  <h2>Failures <span class="count">{{FAIL_COUNT}}</span></h2>
  <details class="test-card fail" open>
    <summary>
      <span class="badge fail">FAIL</span>
      <span class="step-id">step-id-here</span>
      <span class="evidence">expected → actual</span>
    </summary>
    <div class="body">
      <dl>
        <dt>URL</dt><dd>http://localhost:3000/path</dd>
        <dt>Action</dt><dd>What was done</dd>
        <dt>Expected</dt><dd>What should have happened</dd>
        <dt>Actual</dt><dd>What happened instead</dd>
      </dl>
      <div class="suggestion">Fix: description of suggested fix</div>
      <div class="screenshot">
        <img src="data:image/png;base64,..." alt="Screenshot of failure">
        <div class="caption">step-id.png — captured at moment of failure</div>
      </div>
    </div>
  </details>
</div>


<div class="section">
  <h2>Passed <span class="count">{{PASS_COUNT}}</span></h2>
  <details class="test-card pass">
    <summary>
      <span class="badge pass">PASS</span>
      <span class="step-id">step-id-here</span>
      <span class="evidence">evidence summary</span>
    </summary>
    <div class="body">
      <dl>
        <dt>URL</dt><dd>http://localhost:3000/path</dd>
        <dt>Evidence</dt><dd>What was observed</dd>
      </dl>
    </div>
  </details>
</div>
  1. 将屏幕截图嵌入为 base64,使 HTML 完全自包含:
# Convert screenshot to base64 data URI
base64 -i .context/ui-test-screenshots/step-id.png | tr -d '\n'
# Use as: src="data:image/png;base64,<output>"

读取 STEP_FAIL 标记中引用的每个屏幕截图文件,将其编码为 base64,并作为 <img src="data:image/png;base64,..."> 嵌入对应的测试卡片中。对于 STEP_PASS,仅在明确截取了屏幕截图时才嵌入(例如,基线屏幕截图)。

  1. 将最终 HTML 写入 .context/ui-test-report.html:
# Write the generated HTML
cat > .context/ui-test-report.html << 'REPORT_EOF'
<!DOCTYPE html>
...generated report...
REPORT_EOF

# Open it for the reviewer
open .context/ui-test-report.html  # macOS
# xdg-open .context/ui-test-report.html  # Linux
  1. 告知用户:Report saved to .context/ui-test-report.html,并询问是否要打开该文件。

规则:

  • 失败部分放在通过部分之前——审核者最先关注的是出错之处
  • 失败卡片默认 open;通过卡片默认折叠
  • 每个 STEP_FAIL 卡片都必须嵌入屏幕截图——如果屏幕截图文件缺失,请在卡片中注明
  • 如果提供了建议/修复方案,请将其加入每个失败卡片
  • 报告必须可离线使用——不使用 CDN 链接或外部资源
  • HTML 文件不得超过 5MB——如果屏幕截图导致文件过大,请降低图像质量,或跳过通过项的基线屏幕截图

对抗性测试模式

将这些模式应用于你测试的每个交互元素。完整模式库(表单、模态框、导航、错误状态、键盘可访问性)请参阅 references/adversarial-patterns.md。

确定性检查

这些检查会生成结构化数据,而非主观判断。应将其作为最有力的断言。

检查项可发现的问题断言
axe-coreWCAG 违规violations.length === 0
控制台错误运行时异常、请求失败错误数组为空
损坏的图像图像缺失或加载失败不存在 naturalWidth === 0 的图像
表单标签缺少无障碍标签的输入项每个输入项的 hasLabel: true

准确的 browse eval 操作步骤请参阅 references/browser-recipes.md。

工作流 B:探索性测试

没有差异、没有计划——只需打开应用并尝试找出问题。当用户说“测试我的应用”“找出错误”或“对这个网站进行 QA”时,使用此工作流。

方法
  1. 探索应用 — 阅读 package.json 以检测框架,然后打开根 URL 并查看快照,了解页面内容
  2. 浏览所有内容 — 点击导航链接,访问所有可访问的页面,并记录页面内容
  3. 测试发现的内容 — 对每个页面应用以下对抗性模式(表单、模态框、导航、键盘、错误状态)
  4. 运行确定性检查 — 在每个页面上检查 axe-core、控制台错误、损坏的图片和表单标签
  5. 报告发现 — 使用 STEP_PASS/STEP_FAIL 标记,并附上失败项的复现步骤

不要试图系统地覆盖所有内容。像用户一样探索,但要以找出问题为目的。Agent 很擅长这个——让它自由探索。

探索性测试提示
  • 从首页开始,然后自然地浏览导航
  • 尝试访问 404 页面(/does-not-exist)——它是自定义页面还是默认页面?
  • 查找空状态(没有数据的页面)
  • 在输入有效内容之前,先用无效内容测试表单
  • 在每个页面上检查移动端视口(375px)——是否出现溢出?
  • 如果应用有身份验证,先使用 cookie-sync

工作流 C:并行测试

使用命名的 browse 会话(BROWSE_SESSION=<name>)并发运行相互独立的测试组。每个会话都有自己的浏览器。适用于本地模式和远程模式。

测试多个页面或类别且希望缩短实际耗时时使用。

阅读 references/parallel-testing.md,了解完整工作流:会话设置、Agent 扇出、身份验证的 cookie-sync,以及结果合并。

设计一致性

检查更改后的 UI 在视觉上是否与应用的其余部分一致。进行视觉或设计检查时,请阅读 references/design-consistency.md。

测试类别

类别方法断言类型
无障碍axe-core + 键盘导航确定性(违规数量)
视觉质量截图 + 启发式评估视觉判断(最不可靠——注明具体情况)
响应式视口扫描 + 截图视觉 + 确定性(溢出检查)
控制台健康状况控制台捕获评估确定性(错误数量)
UX 启发式快照 + UX 法则 + Nielsen's结构化判断(引用具体启发式原则)
错误状态导航至空状态/错误状态前后对比
数据展示对表格/仪表板使用快照元素匹配(列数、格式)
设计一致性截图基准 + 更改页面对比视觉判断(引用具体属性)
探索性自由导航 + 对抗性测试前后对比 + 判断

参考指南(按需加载):

如需查看包含准确命令的示例,了解断言协议的实际用法,请阅读 EXAMPLES.md。

最佳实践

  1. 持对抗性思维 — 尝试破坏功能,而不只是确认它们能正常工作
  2. 每项断言都需要证据 — 快照引用、评估结果或前后差异
  3. 每次交互都要记录前后状态 — 快照、操作、快照、比较
  4. 每次失败都要截图 — 在 STEP_FAIL 时立即运行 browse screenshot,并保存到 .context/ui-test-screenshots/<step-id>.png
  5. 先进行确定性检查 — 在视觉判断前检查 axe-core、控制台错误和表单标签
  6. 对于 localhost,从干净的本地模式开始 — 在首次 browse open 时传入 --local,以确保运行可复现;只有在需要保留现有本地状态时才使用 --auto-connect
  7. 完成后始终运行 browse stop — 并行运行时,停止每个命名会话
  8. 报告失败时附上复现步骤 — 操作、预期结果、实际结果、截图路径和建议
  9. 并行执行互不依赖的测试 — 在已部署的网站上测试多个页面或类别时,使用工作流 C 和命名会话

故障排除

  • “No active page”:运行 browse stop,然后重试。对于僵尸进程:pkill -f "browse.*daemon"
  • 开发服务器无响应:运行 curl http://localhost:<port> — 请用户启动服务器
  • browse eval 搭配 await 失败:改用 .then() — browse eval 不支持顶层 await
  • 找不到元素引用:重新运行 browse snapshot — 页面更新后引用会变化
  • 快照为空:在截取快照前运行 browse wait load 或 browse wait selector ".expected"
  • SPA 深层链接返回 404:先导航到 /,然后再逐步点击
  • 远程身份验证失败:使用 --context <id> 重新运行 cookie-sync,并尝试 --verified
  • 并行会话冲突:确保每条 browse 命令都使用 BROWSE_SESSION=<name> — 若不指定,命令会发送到默认会话
  • 会话无法停止:运行 BROWSE_SESSION=<name> browse stop。对于僵尸进程:pkill -f "browse.*<name>.*daemon"

评论

支持 Markdown