test-setup

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Test Setup

测试框架搭建

This skill scaffolds the automated testing infrastructure for the project. It detects the configured engine, generates the appropriate test runner configuration, creates the standard directory layout, and wires up CI/CD so tests run on every push.
Run this once during the Technical Setup phase, before any implementation begins. A test framework installed at sprint start costs 30 minutes. A test framework installed at sprint four costs 3 sprints.
Output:
tests/
directory structure +
.github/workflows/tests.yml

这个Skill为项目搭建自动化测试基础设施。它会检测已配置的引擎,生成对应的测试运行器配置,创建标准目录结构,并配置CI/CD,确保每次推送代码时自动运行测试。
需在技术设置阶段、任何开发工作开始前运行一次。在Sprint初期安装测试框架仅需30分钟,而在第四个Sprint才安装则会耗费3个Sprint的时间。
输出:
tests/
目录结构 +
.github/workflows/tests.yml

Phase 1: Detect Engine and Existing State

阶段1:检测引擎与现有状态

  1. Read engine config:
    • Read
      .claude/docs/technical-preferences.md
      and extract the
      Engine:
      value.
    • If engine is not configured (
      [TO BE CONFIGURED]
      ), stop: "Engine not configured. Run
      /setup-engine
      first, then re-run
      /test-setup
      ."
  2. Check for existing test infrastructure:
    • Glob
      tests/
      — does the directory exist?
    • Glob
      tests/unit/
      and
      tests/integration/
      — do subdirectories exist?
    • Glob
      .github/workflows/
      — does a CI workflow file exist?
    • Glob
      tests/gdunit4_runner.gd
      (Godot) or
      tests/EditMode/
      (Unity) or
      Source/Tests/
      (Unreal) for engine-specific artifacts.
  3. Report findings:
    • "Engine: [engine]. Test directory: [found / not found]. CI workflow: [found / not found]."
    • If everything already exists AND
      force
      argument was not passed: "Test infrastructure appears to be in place. Re-run with
      /test-setup force
      to regenerate. Proceeding will not overwrite existing test files."
If the
force
argument is passed, skip the "already exists" early-exit and proceed — but still do not overwrite files that already exist at a given path. Only create files that are missing.

  1. 读取引擎配置:
    • 读取
      .claude/docs/technical-preferences.md
      并提取
      Engine:
      的值。
    • 若引擎未配置(值为
      [TO BE CONFIGURED]
      ),则终止操作: "引擎未配置,请先运行
      /setup-engine
      ,再重新运行
      /test-setup
      。"
  2. 检查现有测试基础设施:
    • 查找
      tests/
      目录是否存在?
    • 查找
      tests/unit/
      tests/integration/
      子目录是否存在?
    • 查找
      .github/workflows/
      目录下是否存在CI工作流文件?
    • 查找引擎专属文件,如Godot的
      tests/gdunit4_runner.gd
      、Unity的
      tests/EditMode/
      或Unreal的
      Source/Tests/
  3. 报告检测结果:
    • "引擎:[engine]。测试目录:[已找到/未找到]。CI工作流:[已找到/未找到]。"
    • 若所有内容已存在且未传入
      force
      参数: "测试基础设施已就绪。如需重新生成,请使用
      /test-setup force
      运行。继续操作不会覆盖现有测试文件。"
若传入
force
参数,则跳过"已存在"的提前终止步骤,继续执行——但仍不会覆盖已存在路径下的文件,仅创建缺失的文件。

Phase 2: Present Plan

阶段2:展示执行计划

Based on the engine detected and the existing state, present a plan:
undefined
基于检测到的引擎和现有状态,展示执行计划:
undefined

Test Setup Plan — [Engine]

测试框架搭建计划 — [Engine]

I will create the following (skipping any that already exist):
tests/ unit/ — Isolated unit tests for formulas, state, and logic integration/ — Cross-system tests and save/load round-trips smoke/ — Critical path test list (15-minute manual gate) evidence/ — Screenshot and manual test sign-off records README.md — Test framework documentation
[Engine-specific files — see per-engine details below]
.github/workflows/tests.yml — CI: run tests on every push to main
Estimated time: ~5 minutes to create all files.

Ask: "May I create these files? I will not overwrite any test files that
already exist at these paths."

Do not proceed without approval.

---
我将创建以下内容(已存在的会跳过):
tests/ unit/ — 用于公式、状态和逻辑的独立单元测试 integration/ — 跨系统测试与保存/加载往返测试 smoke/ — 关键路径测试清单(15分钟手动校验) evidence/ — 截图与手动测试签署记录 README.md — 测试框架文档
[引擎专属文件 — 详见下方各引擎说明]
.github/workflows/tests.yml — CI配置:每次推送至main分支时运行测试
预计耗时:约5分钟创建所有文件。

询问:"是否允许我创建这些文件?我不会覆盖任何已存在路径下的测试文件。"

未获得批准前请勿继续执行。

---

Phase 3: Create Directory Structure

阶段3:创建目录结构

After approval, create the following files:
获得批准后,创建以下文件:

tests/README.md

tests/README.md

markdown
undefined
markdown
undefined

Test Infrastructure

测试基础设施

Engine: [engine name + version] Test Framework: [GdUnit4 | Unity Test Framework | UE Automation] CI:
.github/workflows/tests.yml
Setup date: [date]
引擎: [引擎名称 + 版本] 测试框架: [GdUnit4 | Unity Test Framework | UE Automation] CI:
.github/workflows/tests.yml
搭建日期: [日期]

Directory Layout

目录结构

tests/
  unit/           # Isolated unit tests (formulas, state machines, logic)
  integration/    # Cross-system and save/load tests
  smoke/          # Critical path test list for /smoke-check gate
  evidence/       # Screenshot logs and manual test sign-off records
tests/
  unit/           # 独立单元测试(公式、状态机、逻辑)
  integration/    # 跨系统与保存/加载测试
  smoke/          # 用于/smoke-check校验的关键路径测试清单
  evidence/       # 截图日志与手动测试签署记录

Running Tests

运行测试

[Engine-specific command — see below]
[引擎专属命令 — 详见下方]

Test Naming

测试命名规范

  • Files:
    [system]_[feature]_test.[ext]
  • Functions:
    test_[scenario]_[expected]
  • Example:
    combat_damage_test.gd
    test_base_attack_returns_expected_damage()
  • 文件:
    [system]_[feature]_test.[ext]
  • 函数:
    test_[scenario]_[expected]
  • 示例:
    combat_damage_test.gd
    test_base_attack_returns_expected_damage()

Story Type → Test Evidence

需求类型 → 测试证据要求

Story TypeRequired EvidenceLocation
LogicAutomated unit test — must pass
tests/unit/[system]/
IntegrationIntegration test OR playtest doc
tests/integration/[system]/
Visual/FeelScreenshot + lead sign-off
tests/evidence/
UIManual walkthrough OR interaction test
tests/evidence/
Config/DataSmoke check pass
production/qa/smoke-*.md
需求类型所需证据存放位置
逻辑类自动化单元测试 — 必须通过
tests/unit/[system]/
集成类集成测试或游戏测试文档
tests/integration/[system]/
视觉/体验类截图 + 负责人签署
tests/evidence/
UI类手动 walkthrough 或交互测试
tests/evidence/
配置/数据类Smoke测试通过
production/qa/smoke-*.md

CI

CI说明

Tests run automatically on every push to
main
and on every pull request. A failed test suite blocks merging.
undefined
测试会在每次推送至
main
分支和每次提交Pull Request时自动运行。测试套件失败会阻止合并操作。
undefined

Engine-specific files

引擎专属文件

Godot 4 (
Engine: Godot
)

Godot 4 (
Engine: Godot
)

Create
tests/gdunit4_runner.gd
:
gdscript
undefined
创建
tests/gdunit4_runner.gd
:
gdscript
undefined

GdUnit4 test runner — invoked by CI and /smoke-check

GdUnit4 test runner — invoked by CI and /smoke-check

Usage: godot --headless --script tests/gdunit4_runner.gd

Usage: godot --headless --script tests/gdunit4_runner.gd

extends SceneTree
func _init() -> void: var runner := load("res://addons/gdunit4/GdUnitRunner.gd") if runner == null: push_error("GdUnit4 not found. Install via AssetLib or addons/.") quit(1) return var instance = runner.new() instance.run_tests() quit(0)

Create `tests/unit/.gdignore_placeholder` with content:
`# Unit tests go here — one subdirectory per system (e.g., tests/unit/combat/)`

Create `tests/integration/.gdignore_placeholder` with content:
`# Integration tests go here — one subdirectory per system`

Note in the README: **Installing GdUnit4**
  1. Open Godot → AssetLib → search "GdUnit4" → Download & Install
  2. Enable the plugin: Project → Project Settings → Plugins → GdUnit4 ✓
  3. Restart the editor
  4. Verify: res://addons/gdunit4/ exists
undefined
extends SceneTree
func _init() -> void: var runner := load("res://addons/gdunit4/GdUnitRunner.gd") if runner == null: push_error("GdUnit4 not found. Install via AssetLib or addons/.") quit(1) return var instance = runner.new() instance.run_tests() quit(0)

创建 `tests/unit/.gdignore_placeholder`,内容为:
`# Unit tests go here — one subdirectory per system (e.g., tests/unit/combat/)`

创建 `tests/integration/.gdignore_placeholder`,内容为:
`# Integration tests go here — one subdirectory per system`

在README中添加说明:**安装GdUnit4**
  1. 打开Godot → AssetLib → 搜索 "GdUnit4" → 下载并安装
  2. 启用插件:Project → Project Settings → Plugins → GdUnit4 ✓
  3. 重启编辑器
  4. 验证:res://addons/gdunit4/ 目录存在
undefined

Unity (
Engine: Unity
)

Unity (
Engine: Unity
)

Create
tests/EditMode/
placeholder file
tests/EditMode/README.md
:
markdown
undefined
创建
tests/EditMode/
占位文件
tests/EditMode/README.md
:
markdown
undefined

Edit Mode Tests

Edit Mode Tests

Unit tests that run without entering Play Mode. Use for pure logic: formulas, state machines, data validation. Assembly definition required:
tests/EditMode/EditModeTests.asmdef

Create `tests/PlayMode/README.md`:
```markdown
Unit tests that run without entering Play Mode. Use for pure logic: formulas, state machines, data validation. Assembly definition required:
tests/EditMode/EditModeTests.asmdef

创建 `tests/PlayMode/README.md`:
```markdown

Play Mode Tests

Play Mode Tests

Integration tests that run in a real game scene. Use for cross-system interactions, physics, and coroutines. Assembly definition required:
tests/PlayMode/PlayModeTests.asmdef

Note in the README: **Enabling Unity Test Framework**
Window → General → Test Runner (Unity Test Framework is included by default in Unity 2019+)
undefined
Integration tests that run in a real game scene. Use for cross-system interactions, physics, and coroutines. Assembly definition required:
tests/PlayMode/PlayModeTests.asmdef

在README中添加说明:**启用Unity Test Framework**
Window → General → Test Runner (Unity Test Framework is included by default in Unity 2019+)
undefined

Unreal Engine (
Engine: Unreal
or
Engine: UE5
)

Unreal Engine (
Engine: Unreal
Engine: UE5
)

Create
Source/Tests/README.md
:
markdown
undefined
创建
Source/Tests/README.md
:
markdown
undefined

Unreal Automation Tests

Unreal Automation Tests

Tests use the UE Automation Testing Framework. Run via: Session Frontend → Automation → select "MyGame." tests Or headlessly: UnrealEditor -nullrhi -ExecCmds="Automation RunTests MyGame.; Quit"
Test class naming: F[SystemName]Test Test category naming: "MyGame.[System].[Feature]"

---
Tests use the UE Automation Testing Framework. Run via: Session Frontend → Automation → select "MyGame." tests Or headlessly: UnrealEditor -nullrhi -ExecCmds="Automation RunTests MyGame.; Quit"
Test class naming: F[SystemName]Test Test category naming: "MyGame.[System].[Feature]"

---

Phase 4: Create CI/CD Workflow

阶段4:创建CI/CD工作流

Godot 4

Godot 4

Create
.github/workflows/tests.yml
:
yaml
name: Automated Tests

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    name: Run GdUnit4 Tests
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          lfs: true

      - name: Run GdUnit4 Tests
        uses: MikeSchulze/gdUnit4-action@v1
        with:
          godot-version: '[VERSION FROM docs/engine-reference/godot/VERSION.md]'
          paths: |
            tests/unit
            tests/integration
          report-name: test-results

      - name: Upload Test Results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-results
          path: reports/
创建
.github/workflows/tests.yml
:
yaml
name: Automated Tests

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    name: Run GdUnit4 Tests
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          lfs: true

      - name: Run GdUnit4 Tests
        uses: MikeSchulze/gdUnit4-action@v1
        with:
          godot-version: '[VERSION FROM docs/engine-reference/godot/VERSION.md]'
          paths: |
            tests/unit
            tests/integration
          report-name: test-results

      - name: Upload Test Results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-results
          path: reports/

Unity

Unity

Create
.github/workflows/tests.yml
:
yaml
name: Automated Tests

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    name: Run Unity Tests
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          lfs: true

      - name: Run Edit Mode Tests
        uses: game-ci/unity-test-runner@v4
        env:
          UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
        with:
          testMode: editmode
          artifactsPath: test-results/editmode

      - name: Run Play Mode Tests
        uses: game-ci/unity-test-runner@v4
        env:
          UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
        with:
          testMode: playmode
          artifactsPath: test-results/playmode

      - name: Upload Test Results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-results
          path: test-results/
Note: Unity CI requires a
UNITY_LICENSE
secret. Add to GitHub repository secrets before the first CI run.
创建
.github/workflows/tests.yml
:
yaml
name: Automated Tests

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    name: Run Unity Tests
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          lfs: true

      - name: Run Edit Mode Tests
        uses: game-ci/unity-test-runner@v4
        env:
          UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
        with:
          testMode: editmode
          artifactsPath: test-results/editmode

      - name: Run Play Mode Tests
        uses: game-ci/unity-test-runner@v4
        env:
          UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
        with:
          testMode: playmode
          artifactsPath: test-results/playmode

      - name: Upload Test Results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-results
          path: test-results/
注意:Unity CI需要配置
UNITY_LICENSE
密钥。请在首次CI运行前添加至GitHub仓库密钥中。

Unreal Engine

Unreal Engine

Create
.github/workflows/tests.yml
:
yaml
name: Automated Tests

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    name: Run UE Automation Tests
    runs-on: self-hosted  # UE requires a local runner with the editor installed

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          lfs: true

      - name: Run Automation Tests
        run: |
          "$UE_EDITOR_PATH" "${{ github.workspace }}/[ProjectName].uproject" \
            -nullrhi -nosound \
            -ExecCmds="Automation RunTests MyGame.; Quit" \
            -log -unattended
        shell: bash

      - name: Upload Logs
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-logs
          path: Saved/Logs/
Note: UE CI requires a self-hosted runner with Unreal Editor installed. Set the
UE_EDITOR_PATH
environment variable on the runner.

创建
.github/workflows/tests.yml
:
yaml
name: Automated Tests

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    name: Run UE Automation Tests
    runs-on: self-hosted  # UE requires a local runner with the editor installed

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          lfs: true

      - name: Run Automation Tests
        run: |
          "$UE_EDITOR_PATH" "${{ github.workspace }}/[ProjectName].uproject" \
            -nullrhi -nosound \
            -ExecCmds="Automation RunTests MyGame.; Quit" \
            -log -unattended
        shell: bash

      - name: Upload Logs
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-logs
          path: Saved/Logs/
注意:UE CI需要安装有Unreal Editor的自托管运行器。请在运行器上设置
UE_EDITOR_PATH
环境变量。

Phase 5: Create Smoke Test Seed

阶段5:创建Smoke测试初始文件

Create
tests/smoke/critical-paths.md
:
markdown
undefined
创建
tests/smoke/critical-paths.md
:
markdown
undefined

Smoke Test: Critical Paths

Smoke Test: Critical Paths

Purpose: Run these 10-15 checks in under 15 minutes before any QA hand-off. Run via:
/smoke-check
(which reads this file) Update: Add new entries when new core systems are implemented.
Purpose: Run these 10-15 checks in under 15 minutes before any QA hand-off. Run via:
/smoke-check
(which reads this file) Update: Add new entries when new core systems are implemented.

Core Stability (always run)

Core Stability (always run)

  1. Game launches to main menu without crash
  2. New game / session can be started from the main menu
  3. Main menu responds to all inputs without freezing
  1. Game launches to main menu without crash
  2. New game / session can be started from the main menu
  3. Main menu responds to all inputs without freezing

Core Mechanic (update per sprint)

Core Mechanic (update per sprint)

<!-- Add the primary mechanic for each sprint here as it is implemented --> <!-- Example: "Player can move, jump, and the camera follows correctly" -->
  1. [Primary mechanic — update when first core system is implemented]
<!-- Add the primary mechanic for each sprint here as it is implemented --> <!-- Example: "Player can move, jump, and the camera follows correctly" -->
  1. [Primary mechanic — update when first core system is implemented]

Data Integrity

Data Integrity

  1. Save game completes without error (once save system is implemented)
  2. Load game restores correct state (once load system is implemented)
  1. Save game completes without error (once save system is implemented)
  2. Load game restores correct state (once load system is implemented)

Performance

Performance

  1. No visible frame rate drops on target hardware (60fps target)
  2. No memory growth over 5 minutes of play (once core loop is implemented)

---
  1. No visible frame rate drops on target hardware (60fps target)
  2. No memory growth over 5 minutes of play (once core loop is implemented)

---

Phase 6: Post-Setup Summary

阶段6:搭建完成总结

After writing all files, report:
Test infrastructure created for [engine].

Files created:
- tests/README.md
- tests/unit/ (directory)
- tests/integration/ (directory)
- tests/smoke/critical-paths.md
- tests/evidence/ (directory)
[engine-specific files]
- .github/workflows/tests.yml

Next steps:
1. [Engine-specific install step, e.g., "Install GdUnit4 via AssetLib"]
2. Write your first test: create tests/unit/[first-system]/[system]_test.[ext]
3. Run `/qa-plan sprint` before your first sprint to classify stories and set
   test evidence requirements
4. `/smoke-check` before every QA hand-off

Gate note: /gate-check Technical Setup → Pre-Production now requires:
- tests/ directory with unit/ and integration/ subdirectories
- .github/workflows/tests.yml
- At least one example test file
Run /test-setup and write one example test before advancing.

Verdict: **COMPLETE** — test framework scaffolded and CI/CD wired up.

所有文件创建完成后,输出报告:
已为[engine]创建测试基础设施。

已创建文件:
- tests/README.md
- tests/unit/ (目录)
- tests/integration/ (目录)
- tests/smoke/critical-paths.md
- tests/evidence/ (目录)
[引擎专属文件]
- .github/workflows/tests.yml

后续步骤:
1. [引擎专属安装步骤,例如:"通过AssetLib安装GdUnit4"]
2. 编写你的第一个测试:创建 tests/unit/[first-system]/[system]_test.[ext]
3. 在首个Sprint前运行 `/qa-plan sprint` 对需求进行分类,并设置测试证据要求
4. 每次QA交付前运行 `/smoke-check`

校验说明:/gate-check Technical Setup → Pre-Production 现在要求:
- 包含unit/和integration/子目录的tests/目录
- .github/workflows/tests.yml
- 至少一个示例测试文件
请在推进前运行/test-setup并编写一个示例测试。

结论:**完成** — 测试框架已搭建完成,CI/CD已配置就绪。

Collaborative Protocol

协作规则

  • Never overwrite existing test files — only create files that are missing. If a test runner file exists, leave it as-is.
  • Always ask before creating files — Phase 2 requires explicit approval.
  • Engine detection is non-negotiable — if the engine is not configured, stop and redirect to
    /setup-engine
    . Do not guess.
  • force
    flag skips the "already exists" early-exit but never overwrites.
    It means "create any missing files even if the directory already exists."
  • For Unity CI, note that the
    UNITY_LICENSE
    secret must be configured manually. Do not attempt to automate license management.
  • 切勿覆盖现有测试文件 — 仅创建缺失的文件。若测试运行器文件已存在,请保持原样。
  • 创建文件前务必获得批准 — 阶段2需要明确的批准。
  • 引擎检测不可省略 — 若引擎未配置,请终止操作并引导用户运行
    /setup-engine
    ,切勿猜测。
  • force
    参数会跳过"已存在"的提前终止步骤,但仍不会覆盖文件
    。它的含义是"即使目录已存在,也创建所有缺失的文件"。
  • 对于Unity CI,请注意
    UNITY_LICENSE
    密钥必须手动配置,请勿尝试自动化许可证管理。