关于 game-qa
面向浏览器游戏的 Playwright QA 技能,指导 QA 工程师编写自动化测试,覆盖玩法、视觉、性能与无障碍。提供测试模式、游戏状态检查和移动端测试参考。
主要功能
- 01玩法行为测试
- 02视觉回归与截图测试
- 03性能和 FPS 检查
- 04无障碍测试
- 05游戏状态与时间控制模式
适用场景
- 01验证场景流程、输入和计分
- 02比较游戏场景截图
- 03检查性能预算与无障碍问题
MCP 相关
文档包含 Playwright MCP 服务的设置和使用参考,说明何时使用 MCP 检查,而非脚本化测试。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ playableintelligence/ game-creator --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 modules
项目设置
在游戏项目中添加 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 调用(除非已模拟,例如用
page.route()模拟 Play.fun SDK) - 主观视觉质量——使用 MCP 评估“效果看起来好吗?”