mcpField
P
playwright-interactive-sandbox

playwright-interactive-sandbox

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

关于 playwright-interactive-sandbox

playwright-interactive-sandbox 是一项使用 Playwright 对 Web 应用改动进行端到端功能与视觉 QA 的技能。它面向需要明确覆盖用户控件、视口适配、探索性检查并保存截图证据的开发流程。

主要功能

  1. 01建立共享 QA 检查清单
  2. 02编写精简的 Playwright 脚本
  3. 03测试桌面与移动端流程
  4. 04分别进行功能和视觉 QA
  5. 05检查视口适配及界面状态
  6. 06保存截图证据

适用场景

  1. 01验证 Web 应用改动后的流程
  2. 02检查交互控件和状态变化
  3. 03检查响应式布局与触控行为
  4. 04用截图记录视觉 QA

安装

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

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

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

详细介绍

核心工作流

  1. 测试前编写简要的 QA 清单:
    • 根据三个来源编制清单:用户提出的需求、实际实现的用户可见功能或行为,以及你预计会在最终回复中作出的声明。
    • 以上三个来源中出现的任何内容,在签核前都必须对应至少一项 QA 检查。
    • 列出你打算签核的用户可见声明。
    • 列出每个有意义的面向用户的控件、模式切换或已实现的交互行为。
    • 列出每个控件或已实现行为可能导致的状态变化或视图变化。
    • 将此清单用作功能 QA 和视觉 QA 的共享覆盖范围列表。
    • 对于每项声明或控件-状态组合,注明预期的功能检查、必须进行视觉检查的具体状态,以及预期要捕获的证据。
    • 如果某项需求在视觉上很重要但较为主观,请将其转换为可观察的 QA 检查,而不是让它停留在隐含状态。
    • 至少添加 2 个探索性或偏离正常流程的场景,以发现脆弱行为。
  2. 在持久 TTY 会话中启动或确认任何必需的开发服务器。
  3. 为已更改的流程编写专用的 Playwright 验证脚本。
  4. 先运行桌面脚本;如果更改会影响移动端布局或触控行为,再添加移动端脚本。
  5. 每次更改代码后,都从干净的 Node.js 进程重新运行验证脚本。
  6. 使用正常的用户输入进行功能 QA。
  7. 单独进行视觉 QA。
  8. 验证视口适配情况,并截取支持相关声明所需的屏幕截图。
  9. 保存成功运行所生成的屏幕截图文件。

桌面验证脚本

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

在此沙盒中,Playwright 浏览器预装在 /ms-playwright 下,且 PLAYWRIGHT_BROWSERS_PATH 可能已设为该位置。不要假定默认缓存路径为 ~/.cache/ms-playwright。

在此 Debian 沙盒中,Playwright 应使用无头模式。除非环境明确提供 X 服务器,否则不要浪费尝试次数去试有头模式。

在此 Debian 沙盒中,Playwright 应使用无头模式。除非环境明确提供 X 服务器,否则不要浪费尝试次数去试有头模式。

在此 Debian 沙盒中,Playwright 应使用无头模式。除非环境明确提供 X 服务器,否则不要浪费尝试次数去试有头模式。

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(() => {});
}

主流程使用此模式。脚本应聚焦于你需要验证的确切行为。

如需确认 Playwright 浏览器路径和已安装的浏览器文件,可以运行:

echo "$PLAYWRIGHT_BROWSERS_PATH"
ls -al /ms-playwright

示例检查运行:

node /tmp/playwright-verify-desktop.mjs

移动端验证脚本

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

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 脚本。
  • 更改代码后,从干净的进程重新运行验证脚本,不要尝试在多次运行之间保留状态。
  • 每个脚本都应范围明确:验证一项已更改的流程、其主要断言,以及对应的屏幕截图文件。
  • 如果桌面端和移动端都需要验证,请分别运行脚本或单独调用脚本,而不要使用一个大型的有状态脚本。

检查清单

会话循环
  • 为当前验证轮次编写并运行 Node.js Playwright 验证脚本。
  • 从当前工作区启动目标 Web 应用。
  • 进行代码更改。
  • 针对该更改,使用正确的方式重新加载或重启。
  • 如果探索发现其他控件、状态或可见声明,请更新共享 QA 清单。
  • 重新运行功能 QA。
  • 重新运行视觉 QA。
  • 只有在当前状态就是你要评估的状态后,才捕获最终文件。
重新加载决策
  • 仅渲染器更改:重新加载现有页面。
  • 如果不确定当前脚本是否仍适用于更改后的行为,请重新运行干净的脚本,而不是猜测。
功能 QA
  • 使用真实用户控件进行签核:键盘、鼠标、点击、触控,或等效的 Playwright 输入 API。
  • 至少验证一条端到端关键流程。
  • 确认该流程的可见结果,而不只是内部状态。
  • 对于实时应用或动画较多的应用,在实际交互节奏下验证行为。
  • 按照共享 QA 清单进行测试,不要临时抽查。
  • 签核前至少覆盖每个明显可见的控件一次,不要只测试主要的顺利路径。
  • 对于清单中的可逆控件或有状态切换项,测试完整周期:初始状态、变更后的状态,以及恢复到初始状态。
  • 脚本化检查通过后,使用常规输入进行 30-90 秒的简短探索,而不是只遵循预设路径。
  • 如果探索过程中发现新的状态、控件或声明,请将其加入共享 QA 清单,并在签核前覆盖。
  • page.evaluate(...) 可以检查或准备状态,但不算作签核输入。
视觉 QA
  • 将视觉 QA 视为独立于功能 QA 的检查。
  • 使用测试前定义并在 QA 过程中更新的同一份共享 QA 清单;不要从另一份未明确列出的清单开始视觉检查。
  • 重述面向用户的声明,并逐一明确验证;不要假设功能检查通过就能证明视觉声明成立。
  • 只有在用户能感知该声明的特定状态下完成检查后,才能签核该声明。
  • 滚动前检查初始视口。
  • 确认初始视图能清晰呈现界面的主要声明;如果核心承诺元素在此处无法清楚辨认,应视为缺陷。
  • 检查所有必需的可见区域,而不只是主要交互区域。
  • 检查共享 QA 清单中已列出的状态和模式;如果任务涉及交互,至少检查一个有意义的交互后状态。
  • 如果动效或过渡属于体验的一部分,除了稳定后的终态,还要检查至少一个过渡中的状态。
  • 如果标签、叠加层、注释、引导或高亮应随内容变化而更新,请在相关状态变更后验证这种对应关系。
  • 对于动态视觉效果或依赖交互的视觉内容,要检查足够长的时间,以判断其稳定性、层级关系和可读性;不要仅凭一张截图签核。
  • 对于加载或交互后内容可能变得更密集的界面,在 QA 期间检查可达到的最密集且合理的状态,而不只是空白、加载中或折叠状态。
  • 如果产品定义了最低支持视口或窗口尺寸,请在该尺寸下单独进行视觉 QA;否则,选择更小但仍符合实际使用情况的尺寸,并明确检查。
  • 区分元素是否存在与实现是否到位:如果预期的操作提示虽然在技术上存在,但因对比度不足、遮挡、裁切或不稳定而无法清楚感知,应视为视觉失败。
  • 如果在评估状态下,任何必需的可见区域被裁切、截断、遮挡或挤出视口,即使页面级滚动指标看起来正常,也应视为缺陷。
  • 检查裁切、溢出、变形、布局失衡、间距不一致、对齐问题、文字难以辨认、对比度不足、层级关系错误,以及不自然的动效状态。
  • 既要评判美观程度,也要评判正确性。界面应显得经过用心设计、协调一致,并且适合当前任务。
  • 签核时优先使用视口截图。整页截图仅作为辅助调试材料;需要仔细检查某个区域时,应截取聚焦该区域的截图。
  • 如果动效导致截图难以判断,请稍候,待界面稳定后再截取实际用于评估的图像。
  • 签核前,明确自问:这个界面有哪些可见部分我还没有仔细检查?
  • 签核前,明确自问:如果用户仔细查看,最可能让这项成果显得难堪的可见缺陷是什么?
签署确认
  • 功能路径已使用正常用户输入通过测试。
  • 已明确对照共享 QA 清单进行覆盖:注明测试过哪些要求、已实现的功能、控件、状态和声明,并指出任何有意排除的内容。
  • 视觉 QA 检查已覆盖所有相关界面。
  • 每项面向用户的声明都有对应的视觉检查和经过审核的截图证据,截图取自该声明所适用的状态及视口或窗口尺寸。
  • 视口适配检查已通过,涵盖预期的初始视图及任何要求的最低支持视口尺寸。
  • UI 不仅功能正常,视觉上也协调一致,且对于该任务而言不显得粗劣。
  • 功能正确性、视口适配和视觉质量必须分别通过;其中一项通过并不代表其他项也通过。
  • 已针对交互式产品完成简短的探索性检查,并在回复中说明该检查的覆盖范围。
  • 如果截图审核与数值检查曾有任何不一致,已在签署确认前调查该差异;截图中可见的裁切属于必须解决的问题,不能以指标为由忽略。
  • 简要确认已检查但未发现的主要缺陷类别。
  • 保留所需的最终成功截图证据,并移除失败或中间运行产生的过时或已替代图像证据。

截图

使用常规 Playwright 截图作为证据和调试材料。

桌面截图:

await page.screenshot({ path: 'playwright-desktop.png', type: 'png' });

移动端截图:

await mobilePage.screenshot({ path: 'playwright-mobile.png', type: 'png' });

局部区域的裁切截图:

const clip = await page.locator('[data-testid="target"]').boundingBox();
if (clip) {
	await page.screenshot({ path: 'playwright-target.png', type: 'png', clip });
}

默认使用视口截图进行签署确认。仅在需要时将整页截图作为辅助调试材料。

视口适配检查(必需)

不要因为主要组件可见,就认定截图符合要求。签署确认前,必须结合截图审核和数值检查,明确验证预期的初始视图是否符合产品要求。

  • 在签署确认前定义预期的初始视图。对于可滚动页面,初始视图指首屏内容。对于应用式外壳、游戏、编辑器、仪表板或工具,初始视图指完整的交互界面,以及使用该界面所需的控件和状态信息。
  • 以截图作为适配情况的主要证据。数值检查用于辅助截图,不能推翻可见的裁切问题。
  • 如果预期的初始视图中任何必需的可见区域被裁切、截断、遮挡或挤出视口,则签署确认不通过,即使页面级滚动指标看起来符合要求也是如此。
  • 如果产品设计为可滚动页面,且初始视图仍能传达核心体验并展示主要行动号召或所需的起始上下文,则滚动是可接受的。
  • 对于固定外壳界面,如果必须滚动才能触及主要交互界面的某部分或必要控件,则滚动不是可接受的解决办法。
  • 不要只依赖文档滚动指标。固定高度外壳、内部面板和隐藏溢出的容器可能会裁切必需的 UI,但页面级滚动检查仍可能显示正常。
  • 检查区域边界,而不仅是文档边界。验证启动状态下每个必需的可见区域都完整位于视口内。
  • 视口适配检查通过,只能证明预期的初始视图可见,且没有意外裁切或滚动需求;不能证明 UI 在视觉上正确或美观。

Web 或渲染器检查:

console.log(
	await page.evaluate(() => ({
		innerWidth: window.innerWidth,
		innerHeight: window.innerHeight,
		clientWidth: document.documentElement.clientWidth,
		clientHeight: document.documentElement.clientHeight,
		scrollWidth: document.documentElement.scrollWidth,
		scrollHeight: document.documentElement.scrollHeight,
		canScrollX: document.documentElement.scrollWidth > document.documentElement.clientWidth,
		canScrollY: document.documentElement.scrollHeight > document.documentElement.clientHeight
	}))
);

如果特定 UI 中裁切是实际可能出现的故障模式,请使用 getBoundingClientRect() 检查必需可见区域,以补充数值检查;对于固定外壳,仅检查文档级指标并不足够。

开发服务器

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

先构建,再仅在端口 4444 上启动已构建的应用:

pnpm run build
PORT=4444 pnpm run start

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

  • 交互式验证完成后,请停止你在端口 4444 上启动的服务进程,以便沙盒在任务其余时间保持干净。
  • 此 Debian 沙盒中没有 fuser。请使用 ss -ltnp | rg ":4444" 查找监听 PID,然后执行 kill <pid>,再运行 ss -ltnp | rg ":4444",确认端口 4444 已不再处于监听状态。
  • 清理后,请移除过时或已被取代的交互式图像产物,只保留最终成功的证据。
  • 交互式验证完成后,请停止你在端口 4444 上启动的服务进程,以便沙盒在任务其余时间保持干净。
  • 此 Debian 沙盒中没有 fuser。请使用 ss -ltnp | rg ":4444" 查找监听 PID,然后执行 kill <pid>,再运行 ss -ltnp | rg ":4444",确认端口 4444 已不再处于监听状态。
  • 交互式验证完成后,请停止你在端口 4444 上启动的服务进程,以便沙盒在任务其余时间保持干净。

常见故障

  • Cannot find module 'playwright':确保当前工作区已安装 playwright 包,并在运行 Node.js 脚本前验证导入是否正常。
  • 已安装 Playwright 包,但似乎缺少浏览器可执行文件:先检查 echo $PLAYWRIGHT_BROWSERS_PATH 和 ls -al /ms-playwright。在此沙盒中,浏览器应位于 /ms-playwright,而非 ~/.cache/ms-playwright。只有当该目录确实不存在或不可用时,才运行 npx playwright install chromium。
  • page.goto: net::ERR_CONNECTION_REFUSED:确保开发服务器仍在持久的 TTY 会话中运行,重新检查端口,并优先使用 http://127.0.0.1:<port>。
  • Node.js 进程意外退出或重置:在干净的进程中重新运行验证脚本。

评论

支持 Markdown