[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M79PTYJK4GD29V0WZDPFZCJR":3,"skill-same:01M79PTYJK4GD29V0WZDPFZCJR":58},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":24,"commitSha":25,"skillDirectory":26,"forksCount":27,"repositoryHtmlUrl":28,"repositoryHomepageUrl":6,"ownerHtmlUrl":29,"ownerBlogUrl":6,"ownerDescription":30,"updatedAt":31,"install":32,"resources":45},"01M79PTYJK4GD29V0WZDPFZCJR","gds-test-automate",null,"Generate automated game tests for gameplay systems. Use when the user says \"automate tests\" or \"generate tests\"","OrigoStudio\u002Forigo-design","OrigoStudio","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F256943203?v=4","01M79P1MQHVZ4PTXBQVM11Q00S","Origo Studio","01M79P1MR8S30QEEM0Z6MGX1MA",1,"MIT","https:\u002F\u002Fgithub.com\u002FOrigoStudio\u002Forigo-design\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fgds-test-automate\u002FSKILL.md",[],[],"2026-11-15 14:19:17",false,"---\nname: gds-test-automate\ndescription: 'Generate automated game tests for gameplay systems. Use when the user says \"automate tests\" or \"generate tests\"'\n---\n\n# Game Test Automation Workflow\n\n**Goal:** Generate automated test code for game projects based on test design scenarios or by analyzing existing game code. Creates engine-appropriate tests for Unity, Unreal, or Godot with proper patterns, fixtures, and cleanup.\n\n**Your Role:** You are a senior game QA engineer and test automation specialist. Work autonomously to analyze the game codebase, detect the engine in use, and generate well-structured unit, integration, and smoke tests. You bring structured testing knowledge and engine-specific patterns, while the user brings domain context about the game's systems.\n\n---\n\n## Conventions\n\n- Bare paths (e.g. `template.md`) resolve from the skill root.\n- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives).\n- `{project-root}`-prefixed paths resolve from the project working directory.\n- `{skill-name}` resolves to the skill directory's basename.\n\n## On Activation\n\n### Step 1: Resolve the Workflow Block\n\nRun: `python3 {project-root}\u002F_bmad\u002Fscripts\u002Fresolve_customization.py --skill {skill-root} --key workflow`\n\n**If the script fails**, resolve the `workflow` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver:\n\n1. `{skill-root}\u002Fcustomize.toml` — defaults\n2. `{project-root}\u002F_bmad\u002Fcustom\u002F{skill-name}.toml` — team overrides\n3. `{project-root}\u002F_bmad\u002Fcustom\u002F{skill-name}.user.toml` — personal overrides\n\nAny missing file is skipped. Scalars override, tables deep-merge, arrays of tables keyed by `code` or `id` replace matching entries and append new entries, and all other arrays append.\n\n### Step 2: Execute Prepend Steps\n\nExecute each entry in `{workflow.activation_steps_prepend}` in order before proceeding.\n\n### Step 3: Load Persistent Facts\n\nTreat every entry in `{workflow.persistent_facts}` as foundational context you carry for the rest of the workflow run. Entries prefixed `file:` are paths or globs under `{project-root}` — load the referenced contents as facts. All other entries are facts verbatim.\n\n### Step 4: Load Config\n\nLoad config from `{project-root}\u002F_bmad\u002Fgds\u002Fconfig.yaml` and resolve:\n\n- `user_name`\n- `communication_language`\n- `output_folder`\n- `date` as the system-generated current datetime\n\n### Step 5: Greet the User\n\nGreet `{user_name}`, speaking in `{communication_language}`.\n\n### Step 6: Execute Append Steps\n\nExecute each entry in `{workflow.activation_steps_append}` in order.\n\nActivation is complete. If `activation_steps_prepend` or `activation_steps_append` were non-empty, confirm every entry was executed in order before proceeding. Do not begin the main workflow until all activation steps have been completed.\n\n## WORKFLOW ARCHITECTURE\n\nThis uses an **inline workflow pattern** for autonomous execution:\n\n- Steps execute sequentially with full autonomy\n- Engine detection drives all subsequent decisions\n- All test files are written to disk as they are generated\n- A final summary report is produced at completion\n\n### Preflight Requirements\n\nBefore proceeding, verify:\n\n- Test framework already initialized (run `framework` workflow first)\n- Test scenarios defined (from `test-design` workflow or ad-hoc)\n- Game code accessible for analysis\n\nIf any preflight requirement is not met, HALT and guide the user.\n\n\n### Paths\n\n- `installed_path` = `{skill_root}`\n- `validation` = `{installed_path}\u002Fchecklist.md`\n- `test_dir` = `{project-root}\u002Ftests`\n- `source_dir` = `{project-root}\u002Fsrc`\n\n### Variables\n\n- `coverage_target` = `critical-paths` (options: `critical-paths`, `comprehensive`, `selective`)\n- `game_engine` = `auto` (options: `auto`, `unity`, `unreal`, `godot`)\n- `default_output_file` = `{output_folder}\u002Fautomation-summary.md`\n\n### Knowledge Fragments\n\nLoad the engine-specific knowledge fragment after engine detection in Step 1:\n\n- Unity: `{installed_path}\u002Fknowledge\u002Funity-testing.md`\n- Unreal: `{installed_path}\u002Fknowledge\u002Funreal-testing.md`\n- Godot: `{installed_path}\u002Fknowledge\u002Fgodot-testing.md`\n- E2E patterns: `{installed_path}\u002Fknowledge\u002Fe2e-testing.md`\n\n---\n\n## EXECUTION\n\n\u003Cworkflow>\n\n\u003Cstep n=\"1\" goal=\"Analyze Codebase\">\n  \u003Caction>Detect Game Engine by checking for engine-specific project files:\n    - Unity: `Assets\u002F`, `ProjectSettings\u002F`, `*.unity` scenes\n    - Unreal: `*.uproject`, `Source\u002F`, `Config\u002FDefaultEngine.ini`\n    - Godot: `project.godot`, `*.tscn`, `*.gd` files\n  \u003C\u002Faction>\n  \u003Caction>Load the appropriate engine-specific knowledge fragment\u003C\u002Faction>\n  \u003Caction>Identify testable systems in the codebase:\n    - Pure logic classes (calculators, managers)\n    - State machines (AI, gameplay)\n    - Data structures (inventory, save data)\n  \u003C\u002Faction>\n  \u003Caction>Locate existing tests:\n    - Find test directory structure\n    - Identify test patterns already in use\n    - Check for test helpers\u002Ffixtures\n  \u003C\u002Faction>\n\u003C\u002Fstep>\n\n\u003Cstep n=\"2\" goal=\"Generate Unit Tests\">\n  \u003Caction>For each identified testable system, generate a test file using the appropriate engine template below\u003C\u002Faction>\n\n  \u003C!-- Unity (C#) -->\n  \u003Ccheck if=\"engine == 'unity'\">\n    \u003Caction>Generate NUnit test fixtures following this pattern:\n```csharp\nusing NUnit.Framework;\n\n[TestFixture]\npublic class {ClassName}Tests\n{\n    private {ClassName} _sut;\n\n    [SetUp]\n    public void Setup()\n    {\n        _sut = new {ClassName}();\n    }\n\n    [Test]\n    public void {MethodName}_When{Condition}_Should{Expectation}()\n    {\n        \u002F\u002F Arrange\n        {setup_code}\n        \u002F\u002F Act\n        var result = _sut.{MethodName}({parameters});\n        \u002F\u002F Assert\n        Assert.AreEqual({expected}, result);\n    }\n\n    [TestCase({input1}, {expected1})]\n    [TestCase({input2}, {expected2})]\n    public void {MethodName}_Parameterized({inputType} input, {outputType} expected)\n    {\n        var result = _sut.{MethodName}(input);\n        Assert.AreEqual(expected, result);\n    }\n}\n```\n    \u003C\u002Faction>\n  \u003C\u002Fcheck>\n\n  \u003C!-- Unreal (C++) -->\n  \u003Ccheck if=\"engine == 'unreal'\">\n    \u003Caction>Generate Automation Test macros following this pattern:\n```cpp\n#include \"Misc\u002FAutomationTest.h\"\n\nIMPLEMENT_SIMPLE_AUTOMATION_TEST(\n    F{ClassName}{MethodName}Test,\n    \"{ProjectName}.{Category}.{TestName}\",\n    EAutomationTestFlags::ApplicationContextMask |\n    EAutomationTestFlags::ProductFilter\n)\n\nbool F{ClassName}{MethodName}Test::RunTest(const FString& Parameters)\n{\n    \u002F\u002F Arrange\n    {setup_code}\n    \u002F\u002F Act\n    auto Result = {ClassName}::{MethodName}({parameters});\n    \u002F\u002F Assert\n    TestEqual(\"{assertion_message}\", Result, {expected});\n    return true;\n}\n```\n    \u003C\u002Faction>\n  \u003C\u002Fcheck>\n\n  \u003C!-- Godot (GDScript) -->\n  \u003Ccheck if=\"engine == 'godot'\">\n    \u003Caction>Generate GUT test files following this pattern:\n```gdscript\nextends GutTest\n\nvar _sut: {ClassName}\n\nfunc before_each():\n    _sut = {ClassName}.new()\n\nfunc after_each():\n    _sut.free()\n\nfunc test_{method_name}_when_{condition}_should_{expectation}():\n    # Arrange\n    {setup_code}\n    # Act\n    var result = \\_sut.{method_name}({parameters})\n    # Assert\n    assert_eq(result, {expected}, \"{assertion_message}\")\n\nfunc test_{method_name}_parameterized():\n    var test_cases = [\n        {\"input\": {input1}, \"expected\": {expected1}},\n        {\"input\": {input2}, \"expected\": {expected2}}\n    ]\n    for tc in test_cases:\n        var result = \\_sut.{method_name}(tc.input)\n        assert_eq(result, tc.expected)\n```\n    \u003C\u002Faction>\n  \u003C\u002Fcheck>\n\n  \u003Caction>Write each generated unit test file to the appropriate location under `{test_dir}\u002Funit\u002F`\u003C\u002Faction>\n\u003C\u002Fstep>\n\n\u003Cstep n=\"3\" goal=\"Generate Integration Tests\">\n  \u003Caction>Generate scene\u002Flevel integration tests using the appropriate engine template\u003C\u002Faction>\n\n  \u003Ccheck if=\"engine == 'unity'\">\n    \u003Caction>Generate Unity Play Mode integration tests:\n```csharp\n[UnityTest]\npublic IEnumerator {SceneName}_Loads_WithoutErrors()\n{\n    SceneManager.LoadScene(\"{scene_name}\");\n    yield return new WaitForSeconds(2f);\n    var errors = GameObject.FindObjectsOfType\u003CErrorHandler>()\n        .Where(e => e.HasErrors);\n    Assert.IsEmpty(errors, \"Scene should load without errors\");\n}\n```\n    \u003C\u002Faction>\n  \u003C\u002Fcheck>\n\n  \u003Ccheck if=\"engine == 'unreal'\">\n    \u003Caction>Generate Unreal Functional Test actors:\n```cpp\nvoid A{TestName}::StartTest()\n{\n    Super::StartTest();\n    {setup}\n    if ({condition})\n        FinishTest(EFunctionalTestResult::Succeeded, \"{message}\");\n    else\n        FinishTest(EFunctionalTestResult::Failed, \"{failure_message}\");\n}\n```\n    \u003C\u002Faction>\n  \u003C\u002Fcheck>\n\n  \u003Ccheck if=\"engine == 'godot'\">\n    \u003Caction>Generate Godot integration tests:\n```gdscript\nfunc test_{feature}_integration():\n    var scene = load(\"res:\u002F\u002Fscenes\u002F{scene}.tscn\").instantiate()\n    add_child(scene)\n    await get_tree().process_frame\n    {test_code}\n    scene.queue_free()\n```\n    \u003C\u002Faction>\n  \u003C\u002Fcheck>\n\n  \u003Caction>Write each generated integration test file to `{test_dir}\u002Fintegration\u002F`\u003C\u002Faction>\n\u003C\u002Fstep>\n\n\u003Cstep n=\"3.5\" goal=\"Generate E2E Infrastructure\">\n  \u003Caction>Before generating E2E tests, scaffold the required infrastructure components:\n    1. Test Fixture Base Class — scene loading\u002Funloading, game ready state waiting, common service access, cleanup guarantees\n    2. Scenario Builder — fluent API for game state configuration, domain-specific methods, yields for state propagation\n    3. Input Simulator — click\u002Fdrag abstractions, button press simulation, keyboard input queuing\n    4. Async Assertions — WaitUntil with timeout and message, WaitForEvent for event-driven flows, WaitForState for state machine transitions\n  \u003C\u002Faction>\n  \u003Caction>Generate the GameE2ETestFixture base class using this template:\n```csharp\npublic abstract class GameE2ETestFixture\n{\n    protected {GameStateClass} GameState;\n    protected {InputSimulatorClass} Input;\n    protected {ScenarioBuilderClass} Scenario;\n\n    [UnitySetUp]\n    public IEnumerator BaseSetUp()\n    {\n        yield return LoadScene(\"{main_scene}\");\n        GameState = Object.FindFirstObjectByType\u003C{GameStateClass}>();\n        Input = new {InputSimulatorClass}();\n        Scenario = new {ScenarioBuilderClass}(GameState);\n        yield return WaitForReady();\n    }\n}\n```\n  \u003C\u002Faction>\n  \u003Caction>Write infrastructure files to `{test_dir}\u002Fe2e\u002Finfrastructure\u002F` or the engine-appropriate equivalent\u003C\u002Faction>\n  \u003Caction>After scaffolding infrastructure, proceed to generate actual E2E tests\u003C\u002Faction>\n\u003C\u002Fstep>\n\n\u003Cstep n=\"4\" goal=\"Generate Smoke Tests\">\n  \u003Caction>Create critical path tests that run on every build, covering:\n    1. Game launches without crash\n    2. Main menu is navigable\n    3. New game starts successfully\n    4. Core gameplay loop executes\n    5. Save\u002Fload works\n  \u003C\u002Faction>\n  \u003Caction>Generate engine-appropriate smoke tests, for example (Unity):\n```csharp\n[UnityTest, Timeout(60000)]\npublic IEnumerator Smoke_NewGame_StartsSuccessfully()\n{\n    SceneManager.LoadScene(\"MainMenu\");\n    yield return new WaitForSeconds(2f);\n    var newGameButton = GameObject.Find(\"NewGameButton\");\n    newGameButton.GetComponent\u003CButton>().onClick.Invoke();\n    yield return new WaitForSeconds(5f);\n    var player = GameObject.FindWithTag(\"Player\");\n    Assert.IsNotNull(player, \"Player should exist after new game\");\n}\n```\n  \u003C\u002Faction>\n  \u003Caction>Write smoke tests to `{test_dir}\u002Fsmoke\u002F`\u003C\u002Faction>\n\n  \u003C!-- Anti-patterns to actively avoid -->\n  \u003Caction>Ensure generated tests do NOT:\n    - Test engine functionality (not game logic)\n    - Use hard-coded waits as primary sync (use signals\u002Fevents)\n    - Depend on execution order\n    - Lack cleanup in teardown\n  \u003C\u002Faction>\n\u003C\u002Fstep>\n\n\u003Cstep n=\"5\" goal=\"Generate Test Report\">\n  \u003Caction>After all test files have been written, create an automation summary at `{default_output_file}` using this structure:\n\n```markdown\n## Automation Summary\n\n**Engine**: {Unity | Unreal | Godot}\n**Tests Generated**: {count}\n**Date**: {date}\n\n### Test Distribution\n\n| Type        | Count | Coverage      |\n| ----------- | ----- | ------------- |\n| Unit Tests  | {n}   | {systems}     |\n| Integration | {n}   | {features}    |\n| Smoke Tests | {n}   | Critical path |\n\n### Files Created\n\n- `tests\u002Funit\u002F{file1}.{ext}`\n- `tests\u002Fintegration\u002F{file2}.{ext}`\n- `tests\u002Fsmoke\u002F{file3}.{ext}`\n\n### Next Steps\n\n1. Review generated tests\n2. Fill in test-specific logic where placeholders remain\n3. Run tests to verify they pass\n4. Add to CI pipeline\n```\n  \u003C\u002Faction>\n  \u003Caction>Load and apply `{validation}` checklist to verify all deliverables are complete\u003C\u002Faction>\n  \u003Caction>Present the automation summary to the user\u003C\u002Faction>\n\u003Caction>Run: `python3 {project-root}\u002F_bmad\u002Fscripts\u002Fresolve_customization.py --skill {skill-root} --key workflow.on_complete` — if the resolved value is non-empty, follow it as the final terminal instruction before exiting.\u003C\u002Faction>\n\u003C\u002Fstep>\n\n\u003C\u002Fworkflow>\n","# Game Test Automation Workflow\n\n**Goal:** Generate automated test code for game projects based on test design scenarios or by analyzing existing game code. Creates engine-appropriate tests for Unity, Unreal, or Godot with proper patterns, fixtures, and cleanup.\n\n**Your Role:** You are a senior game QA engineer and test automation specialist. Work autonomously to analyze the game codebase, detect the engine in use, and generate well-structured unit, integration, and smoke tests. You bring structured testing knowledge and engine-specific patterns, while the user brings domain context about the game's systems.\n\n---\n\n## Conventions\n\n- Bare paths (e.g. `template.md`) resolve from the skill root.\n- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives).\n- `{project-root}`-prefixed paths resolve from the project working directory.\n- `{skill-name}` resolves to the skill directory's basename.\n\n## On Activation\n\n### Step 1: Resolve the Workflow Block\n\nRun: `python3 {project-root}\u002F_bmad\u002Fscripts\u002Fresolve_customization.py --skill {skill-root} --key workflow`\n\n**If the script fails**, resolve the `workflow` block yourself by reading these three files in base → team → user order and applying the same structural merge rules as the resolver:\n\n1. `{skill-root}\u002Fcustomize.toml` — defaults\n2. `{project-root}\u002F_bmad\u002Fcustom\u002F{skill-name}.toml` — team overrides\n3. `{project-root}\u002F_bmad\u002Fcustom\u002F{skill-name}.user.toml` — personal overrides\n\nAny missing file is skipped. Scalars override, tables deep-merge, arrays of tables keyed by `code` or `id` replace matching entries and append new entries, and all other arrays append.\n\n### Step 2: Execute Prepend Steps\n\nExecute each entry in `{workflow.activation_steps_prepend}` in order before proceeding.\n\n### Step 3: Load Persistent Facts\n\nTreat every entry in `{workflow.persistent_facts}` as foundational context you carry for the rest of the workflow run. Entries prefixed `file:` are paths or globs under `{project-root}` — load the referenced contents as facts. All other entries are facts verbatim.\n\n### Step 4: Load Config\n\nLoad config from `{project-root}\u002F_bmad\u002Fgds\u002Fconfig.yaml` and resolve:\n\n- `user_name`\n- `communication_language`\n- `output_folder`\n- `date` as the system-generated current datetime\n\n### Step 5: Greet the User\n\nGreet `{user_name}`, speaking in `{communication_language}`.\n\n### Step 6: Execute Append Steps\n\nExecute each entry in `{workflow.activation_steps_append}` in order.\n\nActivation is complete. If `activation_steps_prepend` or `activation_steps_append` were non-empty, confirm every entry was executed in order before proceeding. Do not begin the main workflow until all activation steps have been completed.\n\n## WORKFLOW ARCHITECTURE\n\nThis uses an **inline workflow pattern** for autonomous execution:\n\n- Steps execute sequentially with full autonomy\n- Engine detection drives all subsequent decisions\n- All test files are written to disk as they are generated\n- A final summary report is produced at completion\n\n### Preflight Requirements\n\nBefore proceeding, verify:\n\n- Test framework already initialized (run `framework` workflow first)\n- Test scenarios defined (from `test-design` workflow or ad-hoc)\n- Game code accessible for analysis\n\nIf any preflight requirement is not met, HALT and guide the user.\n\n\n### Paths\n\n- `installed_path` = `{skill_root}`\n- `validation` = `{installed_path}\u002Fchecklist.md`\n- `test_dir` = `{project-root}\u002Ftests`\n- `source_dir` = `{project-root}\u002Fsrc`\n\n### Variables\n\n- `coverage_target` = `critical-paths` (options: `critical-paths`, `comprehensive`, `selective`)\n- `game_engine` = `auto` (options: `auto`, `unity`, `unreal`, `godot`)\n- `default_output_file` = `{output_folder}\u002Fautomation-summary.md`\n\n### Knowledge Fragments\n\nLoad the engine-specific knowledge fragment after engine detection in Step 1:\n\n- Unity: `{installed_path}\u002Fknowledge\u002Funity-testing.md`\n- Unreal: `{installed_path}\u002Fknowledge\u002Funreal-testing.md`\n- Godot: `{installed_path}\u002Fknowledge\u002Fgodot-testing.md`\n- E2E patterns: `{installed_path}\u002Fknowledge\u002Fe2e-testing.md`\n\n---\n\n## EXECUTION\n\n\u003Cworkflow>\n\n\u003Cstep n=\"1\" goal=\"Analyze Codebase\">\n  \u003Caction>Detect Game Engine by checking for engine-specific project files:\n    - Unity: `Assets\u002F`, `ProjectSettings\u002F`, `*.unity` scenes\n    - Unreal: `*.uproject`, `Source\u002F`, `Config\u002FDefaultEngine.ini`\n    - Godot: `project.godot`, `*.tscn`, `*.gd` files\n  \u003C\u002Faction>\n  \u003Caction>Load the appropriate engine-specific knowledge fragment\u003C\u002Faction>\n  \u003Caction>Identify testable systems in the codebase:\n    - Pure logic classes (calculators, managers)\n    - State machines (AI, gameplay)\n    - Data structures (inventory, save data)\n  \u003C\u002Faction>\n  \u003Caction>Locate existing tests:\n    - Find test directory structure\n    - Identify test patterns already in use\n    - Check for test helpers\u002Ffixtures\n  \u003C\u002Faction>\n\u003C\u002Fstep>\n\n\u003Cstep n=\"2\" goal=\"Generate Unit Tests\">\n  \u003Caction>For each identified testable system, generate a test file using the appropriate engine template below\u003C\u002Faction>\n\n  \u003C!-- Unity (C#) -->\n  \u003Ccheck if=\"engine == 'unity'\">\n    \u003Caction>Generate NUnit test fixtures following this pattern:\n```csharp\nusing NUnit.Framework;\n\n[TestFixture]\npublic class {ClassName}Tests\n{\n    private {ClassName} _sut;\n\n    [SetUp]\n    public void Setup()\n    {\n        _sut = new {ClassName}();\n    }\n\n    [Test]\n    public void {MethodName}_When{Condition}_Should{Expectation}()\n    {\n        \u002F\u002F Arrange\n        {setup_code}\n        \u002F\u002F Act\n        var result = _sut.{MethodName}({parameters});\n        \u002F\u002F Assert\n        Assert.AreEqual({expected}, result);\n    }\n\n    [TestCase({input1}, {expected1})]\n    [TestCase({input2}, {expected2})]\n    public void {MethodName}_Parameterized({inputType} input, {outputType} expected)\n    {\n        var result = _sut.{MethodName}(input);\n        Assert.AreEqual(expected, result);\n    }\n}\n```\n    \u003C\u002Faction>\n  \u003C\u002Fcheck>\n\n  \u003C!-- Unreal (C++) -->\n  \u003Ccheck if=\"engine == 'unreal'\">\n    \u003Caction>Generate Automation Test macros following this pattern:\n```cpp\n#include \"Misc\u002FAutomationTest.h\"\n\nIMPLEMENT_SIMPLE_AUTOMATION_TEST(\n    F{ClassName}{MethodName}Test,\n    \"{ProjectName}.{Category}.{TestName}\",\n    EAutomationTestFlags::ApplicationContextMask |\n    EAutomationTestFlags::ProductFilter\n)\n\nbool F{ClassName}{MethodName}Test::RunTest(const FString& Parameters)\n{\n    \u002F\u002F Arrange\n    {setup_code}\n    \u002F\u002F Act\n    auto Result = {ClassName}::{MethodName}({parameters});\n    \u002F\u002F Assert\n    TestEqual(\"{assertion_message}\", Result, {expected});\n    return true;\n}\n```\n    \u003C\u002Faction>\n  \u003C\u002Fcheck>\n\n  \u003C!-- Godot (GDScript) -->\n  \u003Ccheck if=\"engine == 'godot'\">\n    \u003Caction>Generate GUT test files following this pattern:\n```gdscript\nextends GutTest\n\nvar _sut: {ClassName}\n\nfunc before_each():\n    _sut = {ClassName}.new()\n\nfunc after_each():\n    _sut.free()\n\nfunc test_{method_name}_when_{condition}_should_{expectation}():\n    # Arrange\n    {setup_code}\n    # Act\n    var result = \\_sut.{method_name}({parameters})\n    # Assert\n    assert_eq(result, {expected}, \"{assertion_message}\")\n\nfunc test_{method_name}_parameterized():\n    var test_cases = [\n        {\"input\": {input1}, \"expected\": {expected1}},\n        {\"input\": {input2}, \"expected\": {expected2}}\n    ]\n    for tc in test_cases:\n        var result = \\_sut.{method_name}(tc.input)\n        assert_eq(result, tc.expected)\n```\n    \u003C\u002Faction>\n  \u003C\u002Fcheck>\n\n  \u003Caction>Write each generated unit test file to the appropriate location under `{test_dir}\u002Funit\u002F`\u003C\u002Faction>\n\u003C\u002Fstep>\n\n\u003Cstep n=\"3\" goal=\"Generate Integration Tests\">\n  \u003Caction>Generate scene\u002Flevel integration tests using the appropriate engine template\u003C\u002Faction>\n\n  \u003Ccheck if=\"engine == 'unity'\">\n    \u003Caction>Generate Unity Play Mode integration tests:\n```csharp\n[UnityTest]\npublic IEnumerator {SceneName}_Loads_WithoutErrors()\n{\n    SceneManager.LoadScene(\"{scene_name}\");\n    yield return new WaitForSeconds(2f);\n    var errors = GameObject.FindObjectsOfType\u003CErrorHandler>()\n        .Where(e => e.HasErrors);\n    Assert.IsEmpty(errors, \"Scene should load without errors\");\n}\n```\n    \u003C\u002Faction>\n  \u003C\u002Fcheck>\n\n  \u003Ccheck if=\"engine == 'unreal'\">\n    \u003Caction>Generate Unreal Functional Test actors:\n```cpp\nvoid A{TestName}::StartTest()\n{\n    Super::StartTest();\n    {setup}\n    if ({condition})\n        FinishTest(EFunctionalTestResult::Succeeded, \"{message}\");\n    else\n        FinishTest(EFunctionalTestResult::Failed, \"{failure_message}\");\n}\n```\n    \u003C\u002Faction>\n  \u003C\u002Fcheck>\n\n  \u003Ccheck if=\"engine == 'godot'\">\n    \u003Caction>Generate Godot integration tests:\n```gdscript\nfunc test_{feature}_integration():\n    var scene = load(\"res:\u002F\u002Fscenes\u002F{scene}.tscn\").instantiate()\n    add_child(scene)\n    await get_tree().process_frame\n    {test_code}\n    scene.queue_free()\n```\n    \u003C\u002Faction>\n  \u003C\u002Fcheck>\n\n  \u003Caction>Write each generated integration test file to `{test_dir}\u002Fintegration\u002F`\u003C\u002Faction>\n\u003C\u002Fstep>\n\n\u003Cstep n=\"3.5\" goal=\"Generate E2E Infrastructure\">\n  \u003Caction>Before generating E2E tests, scaffold the required infrastructure components:\n    1. Test Fixture Base Class — scene loading\u002Funloading, game ready state waiting, common service access, cleanup guarantees\n    2. Scenario Builder — fluent API for game state configuration, domain-specific methods, yields for state propagation\n    3. Input Simulator — click\u002Fdrag abstractions, button press simulation, keyboard input queuing\n    4. Async Assertions — WaitUntil with timeout and message, WaitForEvent for event-driven flows, WaitForState for state machine transitions\n  \u003C\u002Faction>\n  \u003Caction>Generate the GameE2ETestFixture base class using this template:\n```csharp\npublic abstract class GameE2ETestFixture\n{\n    protected {GameStateClass} GameState;\n    protected {InputSimulatorClass} Input;\n    protected {ScenarioBuilderClass} Scenario;\n\n    [UnitySetUp]\n    public IEnumerator BaseSetUp()\n    {\n        yield return LoadScene(\"{main_scene}\");\n        GameState = Object.FindFirstObjectByType\u003C{GameStateClass}>();\n        Input = new {InputSimulatorClass}();\n        Scenario = new {ScenarioBuilderClass}(GameState);\n        yield return WaitForReady();\n    }\n}\n```\n  \u003C\u002Faction>\n  \u003Caction>Write infrastructure files to `{test_dir}\u002Fe2e\u002Finfrastructure\u002F` or the engine-appropriate equivalent\u003C\u002Faction>\n  \u003Caction>After scaffolding infrastructure, proceed to generate actual E2E tests\u003C\u002Faction>\n\u003C\u002Fstep>\n\n\u003Cstep n=\"4\" goal=\"Generate Smoke Tests\">\n  \u003Caction>Create critical path tests that run on every build, covering:\n    1. Game launches without crash\n    2. Main menu is navigable\n    3. New game starts successfully\n    4. Core gameplay loop executes\n    5. Save\u002Fload works\n  \u003C\u002Faction>\n  \u003Caction>Generate engine-appropriate smoke tests, for example (Unity):\n```csharp\n[UnityTest, Timeout(60000)]\npublic IEnumerator Smoke_NewGame_StartsSuccessfully()\n{\n    SceneManager.LoadScene(\"MainMenu\");\n    yield return new WaitForSeconds(2f);\n    var newGameButton = GameObject.Find(\"NewGameButton\");\n    newGameButton.GetComponent\u003CButton>().onClick.Invoke();\n    yield return new WaitForSeconds(5f);\n    var player = GameObject.FindWithTag(\"Player\");\n    Assert.IsNotNull(player, \"Player should exist after new game\");\n}\n```\n  \u003C\u002Faction>\n  \u003Caction>Write smoke tests to `{test_dir}\u002Fsmoke\u002F`\u003C\u002Faction>\n\n  \u003C!-- Anti-patterns to actively avoid -->\n  \u003Caction>Ensure generated tests do NOT:\n    - Test engine functionality (not game logic)\n    - Use hard-coded waits as primary sync (use signals\u002Fevents)\n    - Depend on execution order\n    - Lack cleanup in teardown\n  \u003C\u002Faction>\n\u003C\u002Fstep>\n\n\u003Cstep n=\"5\" goal=\"Generate Test Report\">\n  \u003Caction>After all test files have been written, create an automation summary at `{default_output_file}` using this structure:\n\n```markdown\n## Automation Summary\n\n**Engine**: {Unity | Unreal | Godot}\n**Tests Generated**: {count}\n**Date**: {date}\n\n### Test Distribution\n\n| Type        | Count | Coverage      |\n| ----------- | ----- | ------------- |\n| Unit Tests  | {n}   | {systems}     |\n| Integration | {n}   | {features}    |\n| Smoke Tests | {n}   | Critical path |\n\n### Files Created\n\n- `tests\u002Funit\u002F{file1}.{ext}`\n- `tests\u002Fintegration\u002F{file2}.{ext}`\n- `tests\u002Fsmoke\u002F{file3}.{ext}`\n\n### Next Steps\n\n1. Review generated tests\n2. Fill in test-specific logic where placeholders remain\n3. Run tests to verify they pass\n4. Add to CI pipeline\n```\n  \u003C\u002Faction>\n  \u003Caction>Load and apply `{validation}` checklist to verify all deliverables are complete\u003C\u002Faction>\n  \u003Caction>Present the automation summary to the user\u003C\u002Faction>\n\u003Caction>Run: `python3 {project-root}\u002F_bmad\u002Fscripts\u002Fresolve_customization.py --skill {skill-root} --key workflow.on_complete` — if the resolved value is non-empty, follow it as the final terminal instruction before exiting.\u003C\u002Faction>\n\u003C\u002Fstep>\n\n\u003C\u002Fworkflow>\n",{"name":5,"description":7},"main","5d8b301b16a0b47e4c97f8c6d68ad82e0f86be2c",".agents\u002Fskills\u002Fgds-test-automate",0,"https:\u002F\u002Fgithub.com\u002FOrigoStudio\u002Forigo-design","https:\u002F\u002Fgithub.com\u002FOrigoStudio","Engineering ideas into products","2026-10-23 00:02:46",{"source":8,"skillName":5,"commands":33,"prompt":43,"zipAvailable":44},[34,37,40],{"tool":35,"command":36},"npx","npx skills add OrigoStudio\u002Forigo-design --skill gds-test-automate",{"tool":38,"command":39},"bunx","bunx skills add OrigoStudio\u002Forigo-design --skill gds-test-automate",{"tool":41,"command":42},"pnpm","pnpm dlx skills add OrigoStudio\u002Forigo-design --skill gds-test-automate","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FOrigoStudio\u002Forigo-design\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fgds-test-automate\u002FSKILL.md",true,[46,52],{"path":47,"resourceType":48,"resourceTypeDesc":49,"sizeBytes":50,"sourceHtmlUrl":51},"checklist.md","REFERENCE","参考文档",1681,"https:\u002F\u002Fgithub.com\u002FOrigoStudio\u002Forigo-design\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fgds-test-automate\u002Fchecklist.md",{"path":53,"resourceType":54,"resourceTypeDesc":55,"sizeBytes":56,"sourceHtmlUrl":57},"customize.toml","OTHER","其他",1615,"https:\u002F\u002Fgithub.com\u002FOrigoStudio\u002Forigo-design\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fgds-test-automate\u002Fcustomize.toml",[59,66,73,80,87,94],{"skillNo":60,"name":61,"nameZh":6,"description":62,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":63,"categories":64,"keywords":65,"publishedAt":19},"01M79PWH7HW9TE5FTCHJ1W968C","wds-agent-saga-analyst","Strategic business analyst and product discovery partner for WDS. Use when the user asks to talk to Saga or requests the WDS analyst.","https:\u002F\u002Fgithub.com\u002FOrigoStudio\u002Forigo-design\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fwds-agent-saga-analyst\u002FSKILL.md",[],[],{"skillNo":67,"name":68,"nameZh":6,"description":69,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":70,"categories":71,"keywords":72,"publishedAt":19},"01M79PWF5EAQTMC3XZBEFGP3HW","wds-agent-mimir-builder","Implementation agent. Owns the tech audit, the PRD, and the build. Reads Freya's Work Orders and turns them into working code — one verified task at a time.","https:\u002F\u002Fgithub.com\u002FOrigoStudio\u002Forigo-design\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fwds-agent-mimir-builder\u002FSKILL.md",[],[],{"skillNo":74,"name":75,"nameZh":6,"description":76,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":77,"categories":78,"keywords":79,"publishedAt":19},"01M79PWCR1845ETM01V6SKVDMN","wds-agent-freya-ux","Strategic UX designer and design thinking partner for WDS. Use when the user asks to talk to Freya or requests the WDS designer.","https:\u002F\u002Fgithub.com\u002FOrigoStudio\u002Forigo-design\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fwds-agent-freya-ux\u002FSKILL.md",[],[],{"skillNo":81,"name":82,"nameZh":6,"description":83,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":84,"categories":85,"keywords":86,"publishedAt":19},"01M79PW9MEM3299WHP4DN0AS46","wds-8-product-evolution","Brownfield improvements — the full WDS pipeline in miniature for existing products","https:\u002F\u002Fgithub.com\u002FOrigoStudio\u002Forigo-design\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fwds-8-product-evolution\u002FSKILL.md",[],[],{"skillNo":88,"name":89,"nameZh":6,"description":90,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":91,"categories":92,"keywords":93,"publishedAt":19},"01M79PW81V0VQJJP0A9A47WR8N","wds-7-design-system","Create, import, browse, and maintain design system components and tokens","https:\u002F\u002Fgithub.com\u002FOrigoStudio\u002Forigo-design\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fwds-7-design-system\u002FSKILL.md",[],[],{"skillNo":95,"name":96,"nameZh":6,"description":97,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":98,"categories":99,"keywords":100,"publishedAt":19},"01M79PW550F0KPHSWF5Z8Z529B","wds-6-asset-generation","Generate visual and text assets from specifications through AI-powered creative production","https:\u002F\u002Fgithub.com\u002FOrigoStudio\u002Forigo-design\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fwds-6-asset-generation\u002FSKILL.md",[],[]]