mcpField
G
game-qa

game-qa

github.com/hungify测试与质量016 次安装1 周前更新
代码仓库

关于 game-qa

面向浏览器游戏项目的 Playwright QA 技能,提供测试玩法、视觉效果、性能和无障碍性的模式,并介绍暴露游戏状态以供检查。

主要功能

  1. 01玩法与计分测试模式
  2. 02截图回归测试
  3. 03性能与 FPS 检查
  4. 04使用 axe 进行无障碍测试
  5. 05游戏状态检查钩子
  6. 06移动端输入测试模式

适用场景

  1. 01验证游戏场景与玩家输入
  2. 02检查视觉改动前后的截图
  3. 03测试性能预算与无障碍性
  4. 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.md
gameplay-invariants.md
iterate-client.md
mobile-tests.md
playwright-mcp.md
test-patterns.md
visual-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 会在测试前自动启动 Vite
  • reuseExistingServer 会在本地复用正在运行的开发服务器
  • 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 时

  1. 安装 Playwright:npm install -D @playwright/test @axe-core/playwright && npx playwright install chromium
  2. 创建 playwright.config.js,配置游戏开发服务器的端口
  3. 在 main.js 中公开 window.__GAME__、window.__GAME_STATE__ 和 window.__EVENT_BUS__
  4. 创建 tests/fixtures/game-test.js,加入 gamePage fixture
  5. 创建 tests/helpers/seed-random.js,实现确定性行为
  6. 在 tests/e2e/ 中编写测试:
    • game.spec.js — 启动、场景流程、输入、计分、游戏结束
    • visual.spec.js — 对每个场景进行截图回归测试
    • perf.spec.js — 加载时间、FPS 预算
  7. 添加 npm 脚本:test、test:ui、test:headed、test:update-snapshots
  8. 生成初始基准:npm run test:update-snapshots

不要自动化测试的内容

  • 动画对象的精确像素位置(不控制时钟时具有非确定性)
  • 正在进行的游戏截图——移动对象会导致无法获得稳定截图;请改用 MCP
  • 音频播放(Playwright 无法检查音频;可通过 evaluate 测试音频对象是否存在)
  • 外部 API 调用,除非已进行模拟(例如 Play.fun SDK——使用 page.route() 进行模拟)
  • 主观视觉质量——使用 MCP 评估“看起来好吗?”

评论

支持 Markdown