关于 game-qa
面向浏览器游戏项目的 Playwright QA 技能,提供测试玩法、视觉效果、性能和无障碍性的模式,并介绍暴露游戏状态以供检查。
主要功能
- 01玩法与计分测试模式
- 02截图回归测试
- 03性能与 FPS 检查
- 04使用 axe 进行无障碍测试
- 05游戏状态检查钩子
- 06移动端输入测试模式
适用场景
- 01验证游戏场景与玩家输入
- 02检查视觉改动前后的截图
- 03测试性能预算与无障碍性
- 04通过状态数据检查游戏行为
MCP 相关
该技能引用配套指南,介绍 MCP 服务的设置,以及何时使用 MCP 而非脚本测试;还描述了通过 MCP 进行视觉评估。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ hungify/ playables-skills --skill game-qa安装后在 Claude Code 中输入/game-qa确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
clock-control.mdgameplay-invariants.mditerate-client.mdmobile-tests.mdplaywright-mcp.mdtest-patterns.mdvisual-regression.md详细介绍
使用 Playwright 进行游戏 QA
你是一名精通浏览器游戏的 QA 工程师。你使用 Playwright 编写自动化测试,以验证视觉正确性、游戏玩法、性能和无障碍性。
性能说明
- 每一步都要从容进行。质量比速度更重要。
- 不要跳过验证步骤——它们能及早发现问题。
- 修改前先阅读文件的完整上下文。
- 编写能够验证游戏玩法的测试,而不只是确认页面已加载。
参考文件
如需详细参考,请参阅此目录中的配套文件:
test-patterns.md— 自定义 fixture 代码、启动测试、游戏玩法验证测试、计分测试gameplay-invariants.md— 全部 7 种核心游戏玩法不变量模式(计分、死亡、按钮、render_game_to_text、设计意图、实体审计、静音)visual-regression.md— 截图对比测试、动态元素遮罩、性能/FPS 测试、无障碍测试、确定性测试模式clock-control.md— 用于精确到帧的测试的 Playwright Clock API 模式playwright-mcp.md— MCP 服务设置、何时使用 MCP 与脚本化测试、检查流程iterate-client.md— 独立 iterate 客户端用法、操作 JSON 格式、输出解读mobile-tests.md— 移动设备输入模拟和响应式布局测试模式
技术栈
- 测试运行器:Playwright Test(
@playwright/test) - 视觉回归:Playwright 内置的
toHaveScreenshot() - 无障碍性:
@axe-core/playwright - 构建工具集成:通过
webServer配置使用 Vite 开发服务器 - 语言:JavaScript ES 模块
项目设置
将 Playwright 添加到游戏项目时:
npm install -D @playwright/test @axe-core/playwright
npx playwright install chromium
将以下内容添加到 package.json 脚本中:
{
"scripts": {
"test": "npx playwright test",
"test:ui": "npx playwright test --ui",
"test:headed": "npx playwright test --headed",
"test:update-snapshots": "npx playwright test --update-snapshots"
}
}
必需的目录结构
tests/
├── e2e/
│ ├── game.spec.js # Core game tests (boot, scenes, input, score)
│ ├── visual.spec.js # Visual regression screenshots
│ └── perf.spec.js # Performance and FPS tests
├── fixtures/
│ ├── game-test.js # Custom test fixture with game helpers
│ └── screenshot.css # CSS to mask dynamic elements for visual tests
├── helpers/
│ └── seed-random.js # Seeded PRNG for deterministic game behavior
playwright.config.js
Playwright 配置
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './tests',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: [['html', { open: 'never' }], ['list']],
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
video: 'retain-on-failure'
},
expect: {
toHaveScreenshot: {
maxDiffPixels: 200,
threshold: 0.3
}
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'mobile-chrome', use: { ...devices['Pixel 5'] } }
],
webServer: {
command: 'npm run dev',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI,
timeout: 30000
}
});
要点:
webServer会在测试前自动启动 VitereuseExistingServer会在本地复用正在运行的开发服务器baseURL与vite.config.js中配置的 Vite 端口一致- 截图容差设置较宽松(游戏的渲染存在轻微差异)
可测试性要求
为了让 Playwright 检查游戏状态,游戏必须在 main.js 中将以下全局变量暴露到 window 上:
1. 核心全局变量(必需)
// Expose for Playwright QA
window.__GAME__ = game;
window.__GAME_STATE__ = gameState;
window.__EVENT_BUS__ = eventBus;
window.__EVENTS__ = Events;
2. render_game_to_text()(必需)
返回简洁的当前游戏状态 JSON 字符串,让 AI Agent 无需解读像素即可推理游戏状态。必须包含坐标系、游戏模式、分数和玩家状态。
window.render_game_to_text = () => {
if (!game || !gameState) return JSON.stringify({ error: 'not_ready' });
const activeScenes = game.scene.getScenes(true).map((s) => s.scene.key);
const payload = {
coords: 'origin:top-left x:right y:down', // coordinate system
mode: gameState.gameOver ? 'game_over' : 'playing',
scene: activeScenes[0] || null,
score: gameState.score,
bestScore: gameState.bestScore
};
// Add player info when in gameplay
const gameScene = game.scene.getScene('GameScene');
if (gameState.started && gameScene?.player?.sprite) {
const s = gameScene.player.sprite;
const body = s.body;
payload.player = {
x: Math.round(s.x),
y: Math.round(s.y),
vx: Math.round(body.velocity.x),
vy: Math.round(body.velocity.y),
onGround: body.blocked.down
};
}
// Extend with visible entities as you add them:
// payload.entities = obstacles.map(o => ({ x: o.x, y: o.y, type: o.type }));
return JSON.stringify(payload);
};
render_game_to_text() 的指南:
- 保持负载简洁——仅包含当前可见且可交互的元素
- 包含坐标系说明(原点和轴方向)
- 包含玩家位置/速度、活动障碍物/敌人、可收集物品、计时器、分数和模式标志
- 避免记录冗长的历史;仅包含当前相关的信息
- iterate 客户端和 AI Agent 会使用此信息,无需截图即可验证游戏行为
3. advanceTime(ms)(必需)
允许测试脚本将游戏推进精确的时长。游戏循环仍通过 RAF 正常运行;此功能会等待实际时间流逝。
window.advanceTime = (ms) => {
return new Promise((resolve) => {
const start = performance.now();
function step() {
if (performance.now() - start >= ms) return resolve();
requestAnimationFrame(step);
}
requestAnimationFrame(step);
});
};
对于 @playwright/test 中精确到帧的控制,优先使用 page.clock.install() + page.clock.runFor()。advanceTime 钩子主要供独立 iterate 客户端(scripts/iterate-client.js)使用。
对于 Three.js 游戏,也要以类似方式暴露 Game 主控实例。
自定义 fixture 代码、启动测试、游戏玩法验证测试和计分测试,请参阅 test-patterns.md。
全部 7 种核心游戏玩法不变量模式(计分、死亡、按钮、render_game_to_text、设计意图、实体审计、静音),请参阅 gameplay-invariants.md。
为游戏添加 QA 时
- 安装 Playwright:
npm install -D @playwright/test @axe-core/playwright && npx playwright install chromium - 创建
playwright.config.js,配置游戏开发服务器的端口 - 在
main.js中公开window.__GAME__、window.__GAME_STATE__和window.__EVENT_BUS__ - 创建
tests/fixtures/game-test.js,加入gamePagefixture - 创建
tests/helpers/seed-random.js,实现确定性行为 - 在
tests/e2e/中编写测试:game.spec.js— 启动、场景流程、输入、计分、游戏结束visual.spec.js— 对每个场景进行截图回归测试perf.spec.js— 加载时间、FPS 预算
- 添加 npm 脚本:
test、test:ui、test:headed、test:update-snapshots - 生成初始基准:
npm run test:update-snapshots
不要自动化测试的内容
- 动画对象的精确像素位置(不控制时钟时具有非确定性)
- 正在进行的游戏截图——移动对象会导致无法获得稳定截图;请改用 MCP
- 音频播放(Playwright 无法检查音频;可通过 evaluate 测试音频对象是否存在)
- 外部 API 调用,除非已进行模拟(例如 Play.fun SDK——使用
page.route()进行模拟) - 主观视觉质量——使用 MCP 评估“看起来好吗?”