jame581/godotprompter

godot-testing

Use when writing tests for Godot projects — TDD workflow with GUT and gdUnit4, covers both GDScript and C#

First seen Apr 23, 2026

Installation

$ npx skills add jame581/godotprompter --skill godot-testing

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from jame581/godotprompter · top by installs.

npx skills add jame581/godotprompter

Browse all from jame581/godotprompter

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 685
License LICENSE
Default branch master
Open issues 1
Status Active

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 9,564 B
  • docs SUMMARY.md 129 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 118 installs

SKILL.md

Godot Testing

This skill covers test-driven development (TDD) for Godot 4.3+ projects using GUT (Godot Unit Testing) and gdUnit4. It includes framework selection, full RED-GREEN-REFACTOR examples, test structure, running tests in CI, and common testing patterns.

Related skills: godot-code-review for review checklists, dependency-injection for test-friendly architecture, export-pipeline for CI/CD test automation.

Framework Selection

Feature GUT gdUnit4
Language GDScript-first, limited C# GDScript + C# (first-class)
Install AssetLib or git submodule AssetLib or git submodule
Editor integration Built-in GUT panel Built-in inspector + panel
Mocking double() / stub() API mock() / spy() API
Scene testing addchildautofree() auto_free() + scene runner
CI support gut_cmdln.gd CLI script gdunit4_runner CLI script
C# support Minimal (GDScript wrappers only) Native C# assertions + lifecycle
Maturity Established (Godot 3 + 4) Godot 4 focused, actively updated
Best for Pure GDScript projects Mixed GDScript/C# or C#-only

Rule of thumb: Use GUT for GDScript-only projects. Use gdUnit4 for C# projects or when you need first-class C# support and scene runner utilities.


TDD Workflow: RED-GREEN-REFACTOR

The standard Test-Driven Development cycle: write a failing test (RED), write minimal code to pass (GREEN), then refactor without breaking the test. Each step has its own discipline — don't skip RED (you'll write tests that pass trivially), and don't skip REFACTOR (technical debt compounds).

See [references/tdd-workflow.md](references/tdd-workflow.md) for a worked GDScript + C# example walking through all three steps on a HealthComponent.


Test Directory Structure

res://
├── src/
│   └── components/
│       ├── health_component.gd
│       └── HealthComponent.cs
└── tests/
    ├── unit/
    │   ├── test_health_component.gd      # GUT: test_ prefix required
    │   └── HealthComponentTest.cs        # gdUnit4 C#: [TestSuite] attribute
    ├── integration/
    │   ├── test_player_scene.gd
    │   └── PlayerSceneTest.cs
    └── gut_config.json                   # GUT configuration (optional)

Naming conventions

Framework GDScript file C# file Test method prefix/attribute
GUT test_*.gd N/A func test_*()
gdUnit4 test_*.gd *Test.cs func test_*() / [TestCase]

Running Tests

Both frameworks ship a CLI runner. GUT: addons/gut/gutcmdln.gd invoked via godot --headless --path . -s addons/gut/gutcmdln.gd. gdUnit4: --add-gdunit-test-runner argument, or via the editor "GdUnit Tests" dock. CI: tag-triggered or PR-triggered GitHub Action that installs Godot, runs the suite, exits non-zero on failure.

See [references/running-tests.md](references/running-tests.md) for full GUT and gdUnit4 CLI invocations + a copy-pasteable GitHub Actions workflow.


Testing Patterns

Four common patterns: scenes with nodes (instantiate via addchild in beforeeach, free in after_each), signal testing (assert that emitting works and connect-then-emit fires), mocking/doubling (gdUnit4 Mock<T> or hand-rolled fakes via @export injection), async (await yields, signals, frames in tests).

See [references/testing-patterns.md](references/testing-patterns.md) for full code on each pattern (GDScript + C# where applicable).


Common Assertions

GUT assertions

Assertion Description
assert_eq(actual, expected) Equality
assert_ne(actual, expected) Not equal
assert_true(value) Is truthy
assert_false(value) Is falsy
assert_null(value) Is null
assertnotnull(value) Is not null
assert_gt(actual, expected) Greater than
assert_lt(actual, expected) Less than
assert_gte(actual, expected) Greater than or equal
assert_lte(actual, expected) Less than or equal
assert_has(collection, item) Collection contains item
assertdoesnot_have(collection, item) Collection does not contain item
assertstringcontains(str, sub) String contains substring
assertalmosteq(actual, expected, margin) Float equality within margin
assertsignalemitted(obj, signal_name) Signal was emitted
assertsignalnotemitted(obj, signalname) Signal was not emitted

gdUnit4 assertions (GDScript + C#)

GDScript C# Description
assertthat(val).isequal(exp) AssertThat(val).IsEqual(exp) Equality
assertthat(val).isnot_equal(exp) AssertThat(val).IsNotEqual(exp) Not equal
assertthat(val).istrue() AssertThat(val).IsTrue() Is true
assertthat(val).isfalse() AssertThat(val).IsFalse() Is false
assertthat(val).isnull() AssertThat(val).IsNull() Is null
assertthat(val).isnot_null() AssertThat(val).IsNotNull() Is not null
assertthat(val).isgreater(exp) AssertThat(val).IsGreater(exp) Greater than
assertthat(val).isless(exp) AssertThat(val).IsLess(exp) Less than
assertthat(val).isbetween(min, max) AssertThat(val).IsBetween(min, max) In range (inclusive)
assert_that(arr).contains([a, b]) AssertThat(arr).Contains(a, b) Array contains elements
assert_that(str).contains("sub") AssertThat(str).Contains("sub") String contains substring
assertthat(val).isapproximately(exp, margin) AssertThat(val).IsApproximately(exp, margin) Float within margin
assertsignal(mon).isemitted("name") AssertSignal(mon).IsEmitted("name") Signal emitted

What NOT to Test

Avoid testing things that add noise without catching real bugs:

  • Godot engine internals — do not assert that Node.add_child() works or that @export variables show up in the editor
  • Private implementation details — test behavior through the public API; if a refactor breaks a test that covers only private state, the test is wrong
  • Visual/rendering output — pixel-level rendering results are brittle; test the data driving the visuals instead
  • Timing-sensitive floats without margins — use assertalmosteq / IsApproximately for physics values
  • One-liners that wrap a built-in — a property getter that just returns a field needs no test
  • Every possible invalid input — test the documented contract, not every imaginable misuse

Checklist

  • Each test file matches the naming convention for the chosen framework (test_.gd / Test.cs)
  • Tests extend the correct base class (GutTest / GdUnit4.GdUnitTestSuite)
  • Nodes added to the scene tree use addchildautofree or autofree — never manual queuefree()
  • Signals are watched before the action that triggers them
  • Mocks/doubles are used for external dependencies, not for the unit under test
  • Each test covers exactly one behavior (one logical assertion per test)
  • CI workflow runs tests headlessly on every push and PR
  • Flaky async tests use explicit timeouts, not arbitrary sleep durations
  • Tests pass before merging (RED is only acceptable while actively implementing)