Skip to content
Automation
Skill

/gdunit-driver

Run gdUnit4 unit tests and parse results into structured output. Use this skill after writing or modifying code to verify correctness via unit tests, when diagnosing test failures, or when writing new test files. Triggers: "run tests", "test fails", "write a test", any

From plugin
godotmaker
51141 skills7 agents14 hooks
Install
$ npx -y skills add RandallLiuXin/GodotMaker --skill gdunit-driver --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/gdunit-driver

Context preview

The summary Claude sees to decide when to auto-load this skill.

Run gdUnit4 unit tests and parse results into structured output. Use this skill after writing or modifying code to verify correctness via unit tests, when diagnosing test failures, or when writing new test files. Triggers: "run tests", "test fails", "write a test", any

SKILL.md

gdunit-driver.SKILL.md
name: gdunit-driver
description: |
  Run gdUnit4 unit tests and parse results into structured output.
  Use this skill after writing or modifying code to verify correctness via unit tests,
  when diagnosing test failures, or when writing new test files.
  Triggers: "run tests", "test fails", "write a test", any gdUnit4/unit test mention.
  Supports both GDScript (.gd) and C# (.cs) test files.

gdUnit4 Test Driver

$ARGUMENTS

1. Locate the Godot executable

Read the path from the project's config file. This avoids hardcoding paths that differ per machine.

# From the project root:
python tools/agent_runtime.py godot_path

2. Run tests

The CLI runner across all supported versions (v4.x, v5.x, v6.x) is `addons/gdUnit4/bin/GdUnitCmdTool.gd`. The path uses capital-U `gdUnit4/` to match the upstream repo layout — Windows is case-insensitive but Godot's global script registry de-duplicates by exact path string, so a casing mismatch between the runner invocation and the on-disk directory triggers `Class "..." hides a global script class` parse errors and a non-zero exit.

# Single file
"<godot_path>" --headless -s res://addons/gdUnit4/bin/GdUnitCmdTool.gd \
  --add res://test/test_example.gd --ignoreHeadlessMode

# Multiple files
"<godot_path>" --headless -s res://addons/gdUnit4/bin/GdUnitCmdTool.gd \
  --add res://test/test_physics.gd --add res://test/test_spawner.gd \
  --ignoreHeadlessMode

# All tests in a directory
"<godot_path>" --headless -s res://addons/gdUnit4/bin/GdUnitCmdTool.gd \
  --add res://test/ --ignoreHeadlessMode

Notes:

  • Include `--ignoreHeadlessMode` for headless runs.
  • Use `--add` to enqueue test files or directories (repeat the flag for multiples).
  • Runner path needs the `res://` prefix and the capital-U `addons/gdUnit4/` casing.
  • No `::method` syntax for single test methods — run the whole file instead.

C# tests

`GdUnitCmdTool.gd` supports C# test files too, but ensure `dotnet build` passes first — gdUnit4 runs compiled assemblies, not source files.

dotnet build && "<godot_path>" --headless -s res://addons/gdUnit4/bin/GdUnitCmdTool.gd \
  --add res://test/csharp/TestExample.cs --ignoreHeadlessMode

Useful flags

| Flag | Purpose | |------|---------| | `--add <path>` | Add test path to execution (file or directory; repeat to enqueue multiple) | | `--ignoreHeadlessMode` | Allow headless execution | | `--report-directory <path>` | Override report output directory |

Timeout

gdUnit4 has a default test timeout (configurable in `GdUnitSettings`). If tests hang:

  • Check for infinite loops or unresolved `await` calls
  • Tests involving scene tree operations need explicit timeouts on await calls
  • Kill the process after 120 seconds if no output appears

3. Parse results

Stdout parsing

`GdUnitCmdTool.gd` output contains ANSI color codes — strip them before parsing. Format:

Run Test Suite res://test/test_example.gd
  Run Test: res://test/test_example.gd > test_basic_math :PASSED 38ms
  Run Test: res://test/test_example.gd > test_will_fail :FAILED 39ms
  Report:
    line <n/a>: Expecting:
     '2'
     but was
     '1'

Statistics: | 2 tests cases | 0 error | 1 failed | 0 flaky | 0 skipped | 0 orphans |
Executed test suites: (1/1)
Executed test cases: (2/2)
Total time:        128ms
Exit code: 100

Notes:

  • Per-test lines start with `Run Test:`; suite lines with `Run Test Suite`.
  • Duration is reported in milliseconds (`38ms`).
  • Failure line numbers may show `line <n/a>` instead of exact lines.
  • Summary uses `Statistics:` with pipe-delimited counts.
  • Exit code 100 = test failures (not 1).

Extract from each test line:

  • **Name**: the `test_*` function name (after `>`).
  • **Status**: `PASSED`, `FAILED`, `SKIPPED`, `ERROR`.
  • **Duration**: `Nms` after the status.
  • **Failure message**: indented `Report:` lines following a FAILED test (assertion details + source location if available).

JUnit XML report

Use `--report-directory <path>` for JUnit XML reports. The default report directory is `res://reports/`, which maps to project-root `reports/`.

<testsuites>
  <testsuite name="TestExample" tests="4" failures="1" errors="0" skipped="1">
    <testcase name="test_basic_math" classname="TestExample" time="0.002"/>
    <testcase name="test_will_fail" classname="TestExample" time="0.003">
      <failure message="Expecting '2' but was '1'" type="AssertionError">
        at: res://test/test_example.gd:15
      </failure>
    </testcase>
  </testsuite>
</testsuites>

Structured output format

Report results in this format:

## Test Results: test_example.gd

| Test | Status | Duration |
|------|--------|----------|
| test_basic_math | PASS | 0.002s |
| test_string_concat | PASS | 0.001s |
| test_will_fail | FAIL | 0.003s |
| test_skipped | SKIP | 0.000s |

**Summary: 4 total, 2 passed, 1 failed, 1 skipped, 0 errors**

### Failures

**test_will_fail** (res://test/test_example.gd:15)
> Expecting '2' but was '1'

Always include the file:line for failures — the agent (or user) needs this to navigate to the problem.

4. Writing tests

When the agent needs to write a new test file, follow these patterns.

GDScript test structure

# res://test/test_my_system.gd
extends GdUnitTestSuite

# Runs before each test
func before_test() -> void:
    pass

# Runs after each test
func after_test() -> void:
    pass

func test_example() -> void:
    assert_int(2 + 2).is_equal(4)

func test_string_operations() -> void:
    assert_str("hello").contains("ell")

Key assertion API

# Integers
assert_int(value).is_equal(expected)
assert_int(value).is_greater(threshold)
assert_int(value).is_between(low, high)

# Floats
assert_float(value).is_equal_approx(expected, 0.001)

# Strings
assert_str(value).is_equal(expected)
assert_str(value).contains(substring)
assert_str(value).starts_with(prefix)

# Booleans
assert_bool(value).is_true()
assert_bool(value).is_false()

#
Read more
Ships withgodotmaker

Autonomous text-to-game pipeline for Godot, powered by Claude Code,Codex,Opencode

Get the whole plugin