mcpField
P
playwright-in-sandbox

playwright-in-sandbox

github.com/customware-ai测试与质量2508 次安装2 天前更新
代码仓库

关于 playwright-in-sandbox

用于浏览器验证和确定性端到端测试的 Playwright 技能。它指导 Agent 执行交互检查、视觉审查,并为变更后的用户流程建立回归覆盖。

主要功能

  1. 01交互式浏览器验证
  2. 02确定性 E2E 测试编写
  3. 03基于截图的视觉检查
  4. 04选择器与就绪条件指导
  5. 05E2E 数据和产物规范

适用场景

  1. 01在浏览器中验证 UI 变更
  2. 02为工作流添加回归覆盖
  3. 03重写或整合 Playwright 测试

安装

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

$npx skills add https://github.com/customware-ai/skills --skill playwright-in-sandbox

安装后在 Claude Code 中输入/playwright-in-sandbox确认已加载。

详细介绍

Playwright 沙盒

这是用于沙盒浏览器验证和确定性端到端覆盖的主要 Playwright 技能。

请以两种明确模式之一使用:

  1. 交互式沙盒模式:在任务实现状态看起来合理正确后,进行最终浏览器验证。
  2. 确定性 E2E 模式:在完成任务前,为需要可靠回归测试保护的改动流程提供覆盖。

此技能有意保持通用,适用于:

  • Agent 完成 UI 工作后,通过截图驱动的任务级验证来获取浏览器端证据
  • 在下游应用代码库中正式编写或重写 Playwright E2E 测试
  • 在将任务视为完成之前需要进行最终浏览器验证的任务流程

对于仅涉及后端的工作、不值得使用浏览器自动化的一次性页面操作,或尚未了解工作流清单和根因就发生的大范围故障,不要使用此技能。

核心工作流

  1. 操作浏览器前,先编写简要的 QA 清单。
  2. 先确定模式:交互式沙盒模式或确定性 E2E 模式。
  3. 在持久会话中启动或确认应用已运行。
  4. 实现改动,并确保功能状态看起来合理正确,然后再使用 Playwright 进行验收。
  5. 通过交互方式运行改动后的流程,并检查截图作为证据,而不只是检查 DOM 状态。
  6. 记录你了解到的契约:
    • 路由就绪信号
    • 模态框打开和关闭信号
    • 操作启用条件
    • 保存完成信号
    • 持久的 data-testid 或语义选择器
  7. 如果该流程涉及 Bug 修复、工作流、回归关键功能或有实质性改动,应将其纳入确定性 E2E 覆盖。
  8. 如果交互验证显示产品行为有误,就修复产品代码或数据契约。不要通过弱化测试来掩盖错误行为。
  9. 完成任务前,确保改动后的流程同时具备:
    • 成功的交互验证
    • 持久的 E2E 覆盖,或明确说明为何仅保留交互式验证

通用规则

这些规则同时适用于交互式沙盒模式和确定性端到端(E2E)模式。

  • 交互式验证是变更后的签收步骤。不要在实现尚未完成时,把它当作任务中途随意试探的手段。
  • 如果浏览器验证证明产品行为有误,就修复功能或底层数据契约。不要想方设法绕过错误,让测试变绿。
  • 严格遵循仓库的规范 E2E 数据库契约。如果仓库标准是 e2e.db,就使用 e2e.db。如果仓库要求使用 e2e.db,但该文件缺失,就创建或配置 e2e.db,并继续遵循这一契约。不要悄悄退回使用常规应用数据库。
  • 优先查询规范 E2E 数据库或已植入的业务数据,以推导预期值、状态、分配情况和聚合结果。如果仓库使用 better-sqlite3,可以直接检查数据库,在断言 UI 之前确认真实的预期值。
  • 选择器优先级如下:
    1. 明确的 id、data-*、data-testid 或其他由项目维护的语义契约
    2. 可访问角色加稳定的可访问名称
    3. 标签与控件的关联
    4. 稳定的 URL、路径名或查询参数契约
    5. 仅当文本本身就是产品契约时,才使用纯文本选择器
    6. 仅用于有意进行结构检查时,才使用 CSS、XPath 或 DOM 顺序选择器
  • 在签收前,清除失败或已被取代的运行所产生的过期截图、跟踪记录和临时产物。
  • 如果仓库有维护中的全套测试运行、夜间 QA 运行或自动化健康检查,请持续关注其是否实际运行,以及运行结果是否保持通过。针对性检查不能永远取代套件健康检查。
  • 某些迁移中的应用或一次性客户端应用,暂时可能需要比典型的全新应用更广泛的迁移验证覆盖。这是允许的,但质量标准不变:选择器必须确定、数据必须由项目维护、必须遵循真实的用户契约,且不能制造虚假的通过结果。

模式选择

在以下情况下使用交互式沙盒模式
  • 实现已处于合理正确的状态
  • 需要通过最终的浏览器验证,证明变更后的流程确实可供用户使用
  • 需要通过截图证据判断 UI 是否正确
  • 在编写或更新自动化覆盖之前,需要了解或确认就绪门槛、模态框行为或稳定的选择器
在以下情况下使用确定性 E2E 模式
  • 此变更修复了一个 Bug
  • 此任务创建或实质性改变了用户工作流
  • 此流程对业务至关重要,或很可能出现回归
  • 正在重写、整合或弃用旧版 Playwright 覆盖
  • 没有回归保护就不应认为此任务已完成
仅在以下情况下继续使用交互式模式
  • 此变更是探索性的或临时的
  • 此流程尚不够稳定,无法纳入回归覆盖
  • 此任务不会实质性改变受维护的工作流
  • 迁移中的应用或一次性应用需要临时验证,但尚未稳定到可以转为持久的 E2E 覆盖

如果决定不升级为已提交的 E2E 覆盖,请明确说明原因。

共享环境约定

  • 除非仓库明确另有规定,否则优先使用 127.0.0.1,而不是 localhost。
  • 优先遵循仓库明确规定的服务契约。若仓库没有规定,则 4444 是常见的沙盒默认端口。
  • 在沙盒环境中,Playwright 浏览器可能位于 /ms-playwright;不要假设它位于默认缓存路径。
  • 在沙盒环境中,显式以无头模式启动 Chromium:chromium.launch({ headless: true })。
  • 对运行时载荷有疑问时,确认 Playwright 浏览器路径:
echo "$PLAYWRIGHT_BROWSERS_PATH"
ls -al /ms-playwright
  • 在执行 page.goto(...) 之前,确认目标端口确实正在监听,且应用能够响应。
  • 对于标准运行,使用仓库规范的 E2E 数据库约定。如果仓库标准使用 e2e.db,则始终使用 e2e.db。
  • 如果仓库要求使用 e2e.db,但该文件不存在,则在运行测试前创建或准备好 e2e.db。
  • 只有当仓库明确支持隔离验证通道,且你有意隔离工作进程运行时,才使用其他数据库名称或路径。
  • 将交互式产物与已提交的回归测试资源分开。
    • 临时脚本和屏幕截图应放在临时目录或专用产物目录中
    • 已提交的回归测试覆盖应放在 tests/e2e/ 或仓库正式的测试位置
  • 在最终确认前,清除失败或已被取代的运行所产生的过时屏幕截图、追踪记录和临时产物。
  • 并行运行多个重写或验证通道时,应隔离运行时资源:
    • 端口
    • 数据库或种子状态
    • 输出文件夹
    • 屏幕截图和追踪记录

交互式沙盒模式

在实现完成到足以进行验证后,使用此模式确认更改后的用户流程当前可正常运行。

交互模式并不意味着可以不断尝试,直到某次成功。应在实现更改且确信功能理应正常运行后使用此模式,然后通过浏览器对真实用户流程进行最终的视觉和功能验证。

QA 清单

根据以下三个来源编制清单:

  • 用户提出的需求
  • 你实现或更改的用户可见行为
  • 你预计会在最终回复中提出的声明

以上任一来源中出现的内容,在最终确认前都必须对应至少一项 QA 检查。

列出:

  • 你打算最终确认的用户可见声明
  • 每个有意义的控件、模式切换或已实现的交互行为
  • 每个控件可能导致的状态变化或视图变化
  • 至少两个探索性探测或偏离正常流程的探测
桌面端验证脚本

将 TARGET_URL 设置为你正在调试的应用地址。优先使用 127.0.0.1,而不是 localhost。

import { chromium } from "playwright";

const TARGET_URL = "http://127.0.0.1:4444";
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
  viewport: { width: 1600, height: 900 },
});
const page = await context.newPage();

try {
  await page.goto(TARGET_URL, { waitUntil: "domcontentloaded" });
  console.log("Loaded:", await page.title());

  // Add the task-specific interactions and assertions here.

  await page.screenshot({ path: "playwright-desktop.png", type: "png" });
} finally {
  await context.close().catch(() => {});
  await browser.close().catch(() => {});
}
移动端验证脚本

如果任务涉及响应式布局或触控行为,请使用单独的移动端脚本。

import { chromium } from "playwright";

const TARGET_URL = "http://127.0.0.1:4444";
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
  viewport: { width: 390, height: 844 },
  isMobile: true,
  hasTouch: true,
});
const page = await context.newPage();

try {
  await page.goto(TARGET_URL, { waitUntil: "domcontentloaded" });
  console.log("Loaded mobile:", await page.title());

  // Add the task-specific interactions and assertions here.

  await page.screenshot({ path: "playwright-mobile.png", type: "png" });
} finally {
  await context.close().catch(() => {});
  await browser.close().catch(() => {});
}
迭代模型
  • 针对每个专注的流程,使用一个独立的 Node.js 验证脚本。
  • 代码更改后,从干净进程重新运行验证脚本,不要尝试在多次运行之间保留状态。
  • 让每个脚本保持精简:只包含一项更改后的流程、其主要断言和屏幕截图产物。
  • 如果桌面端和移动端都需要验证,请运行单独的脚本或分别调用脚本。
  • 屏幕截图审查是约定的一部分。不要仅凭 DOM 断言就进行最终确认。
交互式检查清单
会话循环
  • 编写 QA 清单
  • 更改代码
  • 针对当前流程运行 Playwright 验证脚本,进行最终浏览器验证
  • 使用真实用户输入重新进行功能 QA
  • 单独重新进行视觉 QA
  • 仅在 UI 处于实际评估的状态后,才捕获最终产物
  • 记录可用于正式 E2E 的选择器和就绪条件
功能 QA
  • 使用真实用户控件进行验收:键盘、鼠标、点击、触摸或等效的 Playwright 输入 API。
  • 至少验证一个端到端关键流程。
  • 确认该流程的可见结果,而不只是内部状态。
  • 按照共享 QA 清单逐项检查,不要临时抽查。
  • 验收前至少覆盖每个明显可见的控件一次,而不只是验证顺利路径。
  • 脚本化检查通过后,使用常规输入进行简短的探索性检查。
  • page.evaluate(...) 可以检查或预置状态,但不算作验收输入。
视觉 QA
  • 将视觉 QA 与功能 QA 分开处理。
  • 在相关状态下明确验证每项可见声明。
  • 滚动前检查初始视口。
  • 检查 QA 期间能够到达的最复杂真实状态。
  • 留意裁切、溢出、变形、对比度不足、图层错乱、动画不自然以及过期浮层。
  • 如果 UI 之所以“能用”,只是因为没有注意到隐藏的阻挡元素,那么该流程还不能通过验收。
交互式验收
  • 使用常规用户输入通过了功能路径
  • 视觉检查覆盖了整个相关界面
  • 针对预期初始视图的视口适配检查已通过
  • 最终截图与待验收的声明相符
  • 最终回复中说明了探索性检查
  • 已记录用于编写 E2E 测试的稳定选择器和就绪条件
  • 已移除失败迭代遗留的过期截图或临时产物

确定性 E2E 模式

在编写或重写真实 Playwright 回归测试时使用此模式。

目标是保护真实功能。如果应用行为有误,就修复应用。不要通过调整测试来保留 bug。

工作流
  1. 从交互式验证已证明的内容开始。
  2. 将已了解的 UI 约定转化为稳定的自动化检查。
  3. 让每个测试专注于一个工作流系列或一个连贯的用户旅程。
  4. 确保每个测试自行准备测试环境,或明确接收所需的环境。
  5. 对值、状态和聚合结果,优先使用规范的预置数据或基于数据库的预期值,而不是测试本身不负责的数据字面量。
  6. 删除或合并旧测试覆盖前,先验证修改后的流程。
  7. 如果要重写脆弱的测试套件,请将每个移除的场景归入以下一类:
    • 保留
    • 有理由地合并
    • 有理由地明确标记为过时
    • 附带明确说明地隔离
选择器层级

如果存在更好的约定,就不要使用偶然出现的文本、通用组合框模式、视觉样式或易受浮层影响且不稳定的 DOM 结构来编写稳定测试。 除非文本本身就是真实的产品约定,否则纯文本选择器只能作为最后手段。

等待与就绪规则
  • 不要默认使用 waitForLoadState("networkidle")。
  • 对于导航,等待 URL 变化并确认页面就绪标记,或等待响应约定并确认就绪标记。
  • 对于对话框,交互前等待明确的打开状态,下一个依赖步骤开始前等待明确的关闭状态。
  • 对于保存操作,等待可观察的保存完成约定。
  • 对于异步控件,先断言控件启用的条件,再点击它。
  • 对于存在浮层、抽屉或命令面板的流程,在与下一个界面交互前,确认它们已关闭。
  • 如果交互因其他界面仍占有焦点或指针事件而失败,应修正就绪模型,而不是不断叠加重试。
导航与断言规则
  • 断言行为,而非实现。
  • 优先关注用户可见的结果,而非内部实现细节。
  • 当数值、状态、名册分配或汇总数据来自预置业务数据时,先根据测试自身的设置或规范数据库契约推导预期值,再断言 UI 与其一致。
  • 仅当文本本身就是契约时,才使用文本断言。
  • 如果真正的契约位于特定卡片、区域、对话框或行中,请避免在整个页面范围内进行宽泛的文本匹配。
  • 不要仅为让测试规范显得全面,就为同一个工作流结果保留多个冗余断言。
  • 除非较弱的契约才是产品真正预期的行为,否则不要通过扩大选择器范围、降低预期或接受当前缺陷来让失败的测试变绿。
严禁事项
  • 将默认的 networkidle 作为主要就绪策略
  • 使用 page.evaluate(...) 断言 UI 可直接呈现的行为
  • 编写涵盖多个工作流的巨型综合测试规范
  • 将 button[role="combobox"] 这类通用选择器作为主要契约
  • 默默复用先前测试遗留的状态
  • 在工作流映射明确之前删除或合并旧测试

失败收敛协议

大量测试失败时,默认不要逐个修补。

  1. 先按根本原因归类失败。
    • 身份验证或引导流程
    • 服务过期或共享端口争用
    • 模态框或遮罩状态
    • 选择器契约缺失
    • 就绪状态缺失
    • 数据或设置不确定性
    • 工作流假设已过时
  2. 先修复共用契约,再处理单个测试。
  3. 如果测试规范的结构有问题,就停止修补并重写该工作流系列。
  4. 如果测试规范因混合了过多工作流而反复损坏,就弃用综合测试规范并将其拆分。

重写治理

  • 覆盖率损失必须明确说明,绝不能意外发生。
  • 每条已移除的旧断言都必须有对应的替代项,或有书面的过时理由。
  • 优先进行有意义的合并,而非重复的绿色检查,但不要悄悄降低用户旅程覆盖率。
  • 仅在以下情况下保留隔离的 fixme 覆盖:
    • 该行为确实受阻
    • 隔离状态已明确标注
    • 该系列的其余部分仍可安全推进
  • 正式的 E2E 资源应保留在已提交的测试目录中,探索性脚本或截图则应放在这些目录之外。

并行重写验证

可以并行进行重写工作,但前提是所有权划分和运行时隔离真实有效。

  • 按工作流系列或互不重叠的文件所有权进行并行处理。
  • 未明确划分所有权时,不要让多个工作者编辑同一个综合测试规范或共用辅助工具。
  • 如果工作者并行验证,请隔离以下内容:
    • 端口
    • 数据库或种子路径
    • 输出文件夹
    • 截图、追踪记录和构建产物
  • 如果无法进行运行时隔离,即使重写代码仍可并行,也要串行执行 Playwright 验证。

全套测试的时效性

  • 保持针对性验证快速,但不要让维护中的全套测试契约变得过时。
  • 如果仓库或自动化技术栈支持每日、每夜或发布前运行全套测试,就应将其视为质量可见性的一部分。
  • 如果预期由自动化 Agent 保持 QA 通过,就应有可观察的证据,说明它们已运行、运行了哪些内容,以及是否持续通过。
  • 针对性测试规范通过,不足以替代对更广泛测试套件的长期维护。

开发服务器

进行本地 Web 调试时,请在持久的 TTY 会话中保持应用运行。不要依赖短生命周期 shell 发起的一次性后台命令。

请先使用仓库文档说明的启动流程。如果没有明确约定,常见的沙盒模式是:

pnpm run build
PORT=4444 pnpm run start

在执行 page.goto(...) 之前,请确认目标端口正在监听且应用能够响应。

交互式验证完成后,请停止自己启动的服务器进程,确保沙盒保持干净,便于继续执行任务。

常见失败模式

  • 浏览器流程之所以通过,只是因为遮罩层或模态框拦截器实际上从未关闭。
  • 测试证明了 DOM 发生变化,却未证明用户可见的流程能够正常运行。
  • 规范使用了错误的名单、种子数据或身份假设,最终“测试”的是假状态。
  • 测试通过适应当前缺陷而变绿,而不是修复应用或数据约定。
  • 测试硬编码了本应从测试自有数据库或种子状态推导出的显示文本、计数或值。
  • 多个工作线程并行重写文件,但验证仍共用一个固定端口和一个可变数据库。
  • 测试套件看起来全绿,只是因为保留了重复测试,而没有妥善整合。
  • 一个大型综合规范持续掩盖独特的覆盖范围,因为没人梳理提取出的规范现在分别负责哪些工作流。

签核要求

  • 存在针对变更流程的交互式验证。
  • 如果该流程对回归测试很重要,也应有持久的端到端覆盖。
  • 浏览器证据应与最终回复中的声明相符。
  • 选择器、等待条件和断言应基于真实的 UI 约定。
  • 应明确说明任何跳过、隔离、整合或弃用的覆盖范围。

评论

支持 Markdown