Skills Agentes

Test Helpers

Genera librerías de helpers de test específicas del motor. Lee los patrones de test existentes y crea tests/helpers/ con assertions, factories y mocks para reducir el boilerplate.

Solicitareadglobgrepwrite
Estrellas
24.4k

en todo el repo

Actividad
43

0–100, la ruta de este skill

Actualizado
hace 3 meses

último commit aquí

Commits
0

últimos 90 días

Contexto
3.1k tok

67 tok en reposo

Paquete
1 archivo

12 KB

Instalar

Funciona con cualquier agente que lea SKILL.md

npx -y skills add Donchitos/Claude-Code-Game-Studios --skill test-helpers --agent claude-code

Se instala solo en este repositorio.

Este skill writes to your files.

Qué hace

  • Genera tests/helpers/ con assertions, factories y mocks adaptados al motor y lenguaje del proyecto
  • Lee los tests existentes (hasta 5 archivos) para replicar sus patrones de setup, aserción y mocking
  • Detecta el motor y framework desde .claude/docs/technical-preferences.md
  • Genera helpers específicos por sistema leyendo la GDD correspondiente
  • Nunca sobrescribe helpers existentes; pide confirmación antes de escribir

Úsalo cuando

  • Después de que /test-setup haya montado el framework por primera vez
  • Cuando varios archivos de test repiten el mismo código de setup
  • Cuando se empieza a escribir tests para un nuevo sistema

No lo uses cuando

    Qué lo activa

    Di cualquiera de estas frases y el agente debería cargar este skill.

    • /test-helpers combat
    • /test-helpers all
    • /test-helpers scaffold
    • Genera los helpers de test para el sistema de combate

    SKILL.md

    En inglés

    Test Helpers

    Writing test cases is faster and more consistent when common setup, teardown, and assertion patterns are abstracted into helpers. This skill generates a tests/helpers/ library tailored to the project's actual engine, language, and systems — so every developer writes less boilerplate and more assertions.

    Output: tests/helpers/ directory with engine-specific helper files

    When to run:

    • After /test-setup scaffolds the framework (first time)
    • When multiple test files repeat the same setup boilerplate
    • When starting to write tests for a new system

    1. Parse Arguments

    Modes:

    • /test-helpers [system-name] — generate helpers for a specific system (e.g., /test-helpers combat)
    • /test-helpers all — generate helpers for all systems with test files
    • /test-helpers scaffold — generate only the base helper library (no system-specific helpers); use this on first run
    • No argument — run scaffold if no helpers exist, else all

    2. Detect Engine and Language

    Read .claude/docs/technical-preferences.md and extract:

    • Engine: value
    • Language: value
    • Framework: from the Testing section

    If engine is not configured: "Engine not configured. Run /setup-engine first."


    3. Load Existing Test Patterns

    Scan the test directory for patterns already in use:

    Glob pattern="tests/**/*_test.*" (all test files)
    

    For a representative sample (up to 5 files), read the test files and extract:

    • Setup patterns (how before_each / setUp / fixtures are written)
    • Common assertion patterns (what is being asserted most often)
    • Object creation patterns (how game objects or scenes are instantiated in tests)
    • Mock/stub patterns (how dependencies are replaced)

    This ensures generated helpers match the project's existing style, not a generic template.

    Also read:

    • design/gdd/systems-index.md — to know which systems exist
    • In-scope GDD(s) — to understand what data types and values need testing
    • docs/architecture/tr-registry.yaml — to map requirements to tested systems

    4. Generate Engine-Specific Helpers

    Godot 4 (GDUnit4 / GDScript)

    Base helper (tests/helpers/game_assertions.gd):

    ## Game-specific assertion utilities for [Project Name] tests.
    ## Extends GdUnitAssertions with domain-specific helpers.
    ##
    ## Usage:
    ##   var assert = GameAssertions.new()
    ##   assert.health_in_range(entity, 0, entity.max_health)
    
    class_name GameAssertions
    extends RefCounted
    
    ## Assert a value is within the inclusive range [min_val, max_val].
    ## Use for any formula output that has defined bounds in a GDD.
    static func assert_in_range(
        value: float,
        min_val: float,
        max_val: float,
        label: String = "value"
    ) -> void:
        assert(
            value >= min_val and value <= max_val,
            "%s %.2f is outside expected range [%.2f, %.2f]" % [label, value, min_val, max_val]
        )
    
    ## Assert a signal was emitted during a callable block.
    ## Usage: assert_signal_emitted(entity, "health_changed", func(): entity.take_damage(10))
    static func assert_signal_emitted(
        obj: Object,
        signal_name: String,
        action: Callable
    ) -> void:
        var emitted := false
        obj.connect(signal_name, func(_args): emitted = true)
        action.call()
        assert(emitted, "Expected signal '%s' to be emitted, but it was not." % signal_name)
    
    ## Assert that a callable does NOT emit a signal.
    static func assert_signal_not_emitted(
        obj: Object,
        signal_name: String,
        action: Callable
    ) -> void:
        var emitted := false
        obj.connect(signal_name, func(_args): emitted = true)
        action.call()
        assert(not emitted, "Expected signal '%s' NOT to be emitted, but it was." % signal_name)
    
    ## Assert a node exists at path within a parent.
    static func assert_node_exists(parent: Node, path: NodePath) -> void:
        assert(
            parent.has_node(path),
            "Expected node at path '%s' to exist." % str(path)
        )
    

    Factory helper (tests/helpers/game_factory.gd):

    ## Factory functions for creating test game objects.
    ## Returns minimal objects configured for unit testing (no scene tree required).
    ##
    ## Usage: var player = GameFactory.make_player(health: 100)
    
    class_name GameFactory
    extends RefCounted
    
    ## Create a minimal player-like object for testing.
    ## Override fields as needed.
    static func make_player(health: int = 100) -> Node:
        var player = Node.new()
        player.set_meta("health", health)
        player.set_meta("max_health", health)
        return player
    

    Scene helper (tests/helpers/scene_runner_helper.gd):

    ## Utilities for scene-based integration tests.
    ## Wraps GdUnitSceneRunner for common patterns.
    
    class_name SceneRunnerHelper
    extends GdUnitTestSuite
    
    ## Load a scene and wait one frame for _ready() to complete.
    func load_scene_and_wait(scene_path: String) -> Node:
        var scene = load(scene_path).instantiate()
        add_child(scene)
        await get_tree().process_frame
        return scene
    

    Unity (NUnit / C#)

    Base helper (tests/helpers/GameAssertions.cs):

    using NUnit.Framework;
    using UnityEngine;
    
    /// <summary>
    /// Game-specific assertion utilities for [Project Name] tests.
    /// Extends NUnit's Assert with domain-specific helpers.
    /// </summary>
    public static class GameAssertions
    {
        /// <summary>
        /// Assert a value is within an inclusive range [min, max].
        /// Use for any formula output defined in GDD Formulas sections.
        /// </summary>
        public static void AssertInRange(float value, float min, float max, string label = "value")
        {
            Assert.That(value, Is.InRange(min, max),
                $"{label} ({value:F2}) is outside expected range [{min:F2}, {max:F2}]");
        }
    
        /// <summary>Assert a UnityEvent or C# event was raised during an action.</summary>
        public static void AssertEventRaised(ref bool wasCalled, System.Action action, string eventName)
        {
            wasCalled = false;
            action();
            Assert.IsTrue(wasCalled, $"Expected event '{eventName}' to be raised, but it was not.");
        }
    
        /// <summary>Assert a component exists on a GameObject.</summary>
        public static void AssertHasComponent<T>(GameObject obj) where T : Component
        {
            var component = obj.GetComponent<T>();
            Assert.IsNotNull(component,
                $"Expected GameObject '{obj.name}' to have component {typeof(T).Name}.");
        }
    }
    

    Factory helper (tests/helpers/GameFactory.cs):

    using UnityEngine;
    
    /// <summary>
    /// Factory methods for creating minimal test objects without loading scenes.
    /// </summary>
    public static class GameFactory
    {
        /// <summary>Create a minimal GameObject with a named component for testing.</summary>
        public static GameObject MakeGameObject(string name = "TestObject")
        {
            var go = new GameObject(name);
            return go;
        }
    
        /// <summary>
        /// Create a ScriptableObject of type T for data-driven tests.
        /// Dispose with Object.DestroyImmediate after test.
        /// </summary>
        public static T MakeScriptableObject<T>() where T : ScriptableObject
        {
            return ScriptableObject.CreateInstance<T>();
        }
    }
    

    Unreal Engine (C++)

    Base helper (tests/helpers/GameTestHelpers.h):

    #pragma once
    
    #include "CoreMinimal.h"
    #include "Misc/AutomationTest.h"
    
    /**
     * Game-specific assertion macros and helpers for [Project Name] automation tests.
     * Include in any test file that needs domain-specific assertions.
     *
     * Usage:
     *   GAME_TEST_ASSERT_IN_RANGE(TestName, DamageValue, 10.0f, 50.0f, TEXT("Damage"));
     */
    
    // Assert a float value is within inclusive range [Min, Max]
    #define GAME_TEST_ASSERT_IN_RANGE(TestName, Value, Min, Max, Label) \
        TestTrue( \
            FString::Printf(TEXT("%s (%.2f) in range [%.2f, %.2f]"), Label, Value, Min, Max), \
            (Value) >= (Min) && (Value) <= (Max) \
        )
    
    // Assert a UObject pointer is valid (not null, not garbage collected)
    #define GAME_TEST_ASSERT_VALID(TestName, Ptr, Label) \
        TestTrue( \
            FString::Printf(TEXT("%s is valid"), Label), \
            IsValid(Ptr) \
        )
    
    // Assert an Actor is in the world (spawned successfully)
    #define GAME_TEST_ASSERT_SPAWNED(TestName, ActorPtr, ClassName) \
        TestNotNull( \
            FString::Printf(TEXT("Spawned actor of class %s"), TEXT(#ClassName)), \
            ActorPtr \
        )
    
    /**
     * Helper to create a minimal test world.
     * Remember to call World->DestroyWorld(false) in teardown.
     */
    namespace GameTestHelpers
    {
        inline UWorld* CreateTestWorld(const FString& WorldName = TEXT("TestWorld"))
        {
            UWorld* World = UWorld::CreateWorld(EWorldType::Game, false);
            FWorldContext& WorldContext = GEngine->CreateNewWorldContext(EWorldType::Game);
            WorldContext.SetCurrentWorld(World);
            return World;
        }
    }
    

    5. Generate System-Specific Helpers

    For [system-name] or all modes, generate a helper per system:

    Read the system's GDD to extract:

    • Data types (entity types, component names)
    • Formula variables and their bounds
    • Common test scenarios mentioned in Edge Cases

    Generate tests/helpers/[system]_factory.[ext] with factory functions specific to that system's objects.

    Example pattern for a combat system (Godot/GDScript):

    ## Factory and assertion helpers for Combat system tests.
    ## Generated by /test-helpers combat on [date].
    ## Based on: design/gdd/combat.md
    
    class_name CombatTestFactory
    extends RefCounted
    
    const DAMAGE_MIN := 0
    const DAMAGE_MAX := 999  # From GDD: damage formula upper bound
    
    ## Create a minimal attacker object for damage formula tests.
    static func make_attacker(attack: float = 10.0, crit_chance: float = 0.0) -> Node:
        var attacker = Node.new()
        attacker.set_meta("attack", attack)
        attacker.set_meta("crit_chance", crit_chance)
        return attacker
    
    ## Create a minimal target object for damage receive tests.
    static func make_target(defense: float = 0.0, health: float = 100.0) -> Node:
        var target = Node.new()
        target.set_meta("defense", defense)
        target.set_meta("health", health)
        target.set_meta("max_health", health)
        return target
    
    ## Assert damage output is within GDD-specified bounds.
    static func assert_damage_in_bounds(damage: float) -> void:
        GameAssertions.assert_in_range(damage, DAMAGE_MIN, DAMAGE_MAX, "damage")
    

    6. Write Output

    Present a summary of what will be created:

    ## Test Helpers to Create
    
    Base helpers (engine: [engine]):
    - tests/helpers/game_assertions.[ext]
    - tests/helpers/game_factory.[ext]
    [engine-specific extras]
    
    System helpers ([mode]):
    - tests/helpers/[system]_factory.[ext]  ← from [system] GDD
    

    Ask: "May I write these helper files to tests/helpers/?"

    Never overwrite existing files. If a file already exists, report: "Skipping [path] — already exists. Remove the file manually if you want it regenerated."

    After writing: Verdict: COMPLETE — helper files created.

    "Helper files created. To use them in a test:

    • Godot: class_name is auto-imported — no explicit import needed
    • Unity: Add using directive or reference the test assembly
    • Unreal: #include \"tests/helpers/GameTestHelpers.h\""

    Collaborative Protocol

    • Never overwrite existing helpers — they may contain hand-written customisations. Only generate new files that don't exist yet
    • Generated code is a starting point — the generated factory functions use metadata patterns for simplicity; adapt to the actual class structure once the code exists
    • Helpers should reflect the GDD — bounds and constants in helpers should trace to GDD Formulas sections, not invented values
    • Ask before writing — always confirm before creating files in tests/

    Next Steps

    • Run /test-setup if the test framework has not been scaffolded yet.
    • Use /dev-story to implement stories — helpers reduce boilerplate in new test files.
    • Run /skill-test to validate other skills that may need helper coverage.

    Reproducido de Donchitos/Claude-Code-Game-Studios bajo licencia MIT. Leer esta página en markdown.

    Archivos

    1 archivo en el paquete. Solo se lee SKILL.md al activarse — las referencias se cargan si el skill decide que las necesita.

    Antes de instalar

    Requiere que el motor esté configurado en .claude/docs/technical-preferences.md (ejecutar /setup-engine primero).

    Detalles

    Creador
    Donchitos
    Categoría
    Testing y QA
    Licencia
    MIT
    Recursos incluidos
    Solo SKILL.md
    Código fuente
    Ver SKILL.md

    Etiquetas

    Más de Donchitos/Claude-Code-Game-Studios

    Este repo incluye 73 skills. Si instalas uno, normalmente ya tienes los demás.

    Adopt

    24.4k

    Onboarding brownfield: audita el cumplimiento de formato de los artefactos existentes, clasifica los vacíos por impacto y genera un plan de migración numerado.

    Costo de contexto al activarse
    4.5k tok
    Tamaño del paquete
    1 archivo
    Última actualización
    hace 3 meses
    herramientas desarrollo

    Crea un Registro de Decisión de Arquitectura (ADR) que documenta una decisión técnica importante, su contexto, alternativas consideradas y consecuencias.

    Costo de contexto al activarse
    4.8k tok
    Tamaño del paquete
    1 archivo
    Última actualización
    hace 3 meses
    documentos

    Valida que la arquitectura del proyecto cubra por completo los GDD: cruza requisitos con ADR, detecta conflictos entre decisiones y compatibilidad de motor, y da un veredicto PASS/CONCERNS/FAIL.

    Costo de contexto al activarse
    6.7k tok
    Tamaño del paquete
    1 archivo
    Última actualización
    hace 3 meses
    herramientas desarrollo

    Autoría guiada, sección por sección, del Art Bible. Crea la especificación de identidad visual que condiciona toda la producción de assets. Se ejecuta tras aprobar /brainstorm y antes de /map-systems o de redactar cualquier GDD.

    Costo de contexto al activarse
    3.7k tok
    Tamaño del paquete
    1 archivo
    Última actualización
    hace 3 meses
    documentos

    Audita los assets del juego según convenciones de nombres, presupuestos de tamaño, formatos estándar y requisitos de pipeline. Identifica assets huérfanos, referencias faltantes e infracciones de estándares.

    Costo de contexto al activarse
    697 tok
    Tamaño del paquete
    1 archivo
    Última actualización
    hace 3 meses
    testing qa

    Genera especificaciones visuales por asset y prompts de generación IA a partir de GDDs, docs de nivel o perfiles de personaje. Produce archivos de spec y actualiza el manifiesto maestro.

    Costo de contexto al activarse
    4.1k tok
    Tamaño del paquete
    1 archivo
    Última actualización
    hace 3 meses
    documentos

    Skills relacionados

    Audita los assets del juego según convenciones de nombres, presupuestos de tamaño, formatos estándar y requisitos de pipeline. Identifica assets huérfanos, referencias faltantes e infracciones de estándares.

    Costo de contexto al activarse
    697 tok
    Tamaño del paquete
    1 archivo
    Última actualización
    hace 3 meses
    testing qa

    Crea un informe de bug estructurado a partir de una descripción o analiza código para identificar bugs potenciales, con pasos de reproducción, severidad y contexto completos.

    Costo de contexto al activarse
    1.5k tok
    Tamaño del paquete
    1 archivo
    Última actualización
    hace 3 meses
    testing qa

    Lee los bugs abiertos en production/qa/bugs/, reevalúa prioridad frente a severidad, los asigna a sprints, detecta tendencias sistémicas y genera un informe de triage.

    Costo de contexto al activarse
    2k tok
    Tamaño del paquete
    1 archivo
    Última actualización
    hace 3 meses
    testing qa