mcpField
G
godot-testing

godot-testing

github.com/jame581Testing & quality889224 installsUpdated 4d ago
Repository

About godot-testing

A Godot 4.3+ testing skill for developers using GUT or gdUnit4. It covers framework choice, TDD, test patterns, and running suites locally and in CI.

Key features

  1. 01GUT 与 gdUnit4 框架选择
  2. 02RED-GREEN-REFACTOR 测试流程
  3. 03测试目录与命名规范
  4. 04命令行及 CI 测试运行
  5. 05场景、信号、模拟与异步测试

Use cases

  1. 01为 GDScript 或 C# 项目选择测试框架
  2. 02按 TDD 流程实现 Godot 功能
  3. 03在本地或 CI 中运行测试套件

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/jame581/godotprompter --skill godot-testing

After installing, type/godot-testingin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

gdunit4-reference.md
gut-reference.md
references/
running-tests.md
tdd-workflow.md
testing-patterns.md

Details

From the project README

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

FeatureGUTgdUnit4
LanguageGDScript-first, limited C#GDScript + C# (first-class)
InstallAssetLib or git submoduleAssetLib or git submodule
Editor integrationBuilt-in GUT panelBuilt-in inspector + panel
Mockingdouble() / stub() APImock() / spy() API
Scene testingadd_child_autofree()auto_free() + scene runner
CI supportgut_cmdln.gd CLI scriptruntest.sh / GdUnitCmdTool.gd
C# supportMinimal (GDScript wrappers only)Native C# assertions + lifecycle
MaturityEstablished (Godot 3 + 4)Godot 4 focused, actively updated
Best forPure GDScript projectsMixed 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 for a worked GDScript + C# example walking through all three steps on a HealthComponent.


Test Directory Structure

res://
├── .gutconfig.json                       # GUT default config file (optional)
├── src/
│   └── components/
│       ├── health_component.gd
│       └── HealthComponent.cs
└── tests/
    ├── unit/
    │   ├── test_health_component.gd      # GUT: test_ prefix (default -gprefix)
    │   └── HealthComponentTest.cs        # gdUnit4 C#: [TestSuite] attribute
    └── integration/
        ├── test_player_scene.gd
        └── PlayerSceneTest.cs
Naming conventions
FrameworkGDScript fileC# fileTest method prefix/attribute
GUTtest_*.gdN/Afunc test_*()
gdUnit4any name (*_test.gd when generated)*Test.csfunc test_*() / [TestCase]

Running Tests

Both frameworks ship a CLI runner. GUT: addons/gut/gut_cmdln.gd invoked via godot --headless --path . -s addons/gut/gut_cmdln.gd -gexit (without -gexit the run never quits). gdUnit4: addons/gdUnit4/runtest.sh -a res://tests (wraps bin/GdUnitCmdTool.gd; under --headless it also needs --ignoreHeadlessMode), or the editor's GdUnit 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 for full GUT and gdUnit4 CLI invocations + a copy-pasteable GitHub Actions workflow.


Testing Patterns

Four common patterns: scenes with nodes (instantiate via add_child in before_each, free in after_each), signal testing (assert that emitting works and connect-then-emit fires), mocking/doubling (gdUnit4 mock() in GDScript; in C#, hand-rolled fakes via @export injection), async (await yields, signals, frames in tests).

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


Common Assertions

GUT assertions
AssertionDescription
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
assert_not_null(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
assert_does_not_have(collection, item)Collection does not contain item
assert_string_contains(str, sub)String contains substring
assert_almost_eq(actual, expected, margin)Float equality within margin
assert_signal_emitted(obj, signal_name)Signal was emitted
assert_signal_not_emitted(obj, signal_name)Signal was not emitted
gdUnit4 assertions (GDScript + C#)
GDScriptC#Description
assert_that(val).is_equal(exp)AssertThat(val).IsEqual(exp)Equality
assert_that(val).is_not_equal(exp)AssertThat(val).IsNotEqual(exp)Not equal
assert_that(val).is_true()AssertThat(val).IsTrue()Is true
assert_that(val).is_false()AssertThat(val).IsFalse()Is false
assert_that(val).is_null()AssertThat(val).IsNull()Is null
assert_that(val).is_not_null()AssertThat(val).IsNotNull()Is not null
assert_that(val).is_greater(exp)AssertThat(val).IsGreater(exp)Greater than
assert_that(val).is_less(exp)AssertThat(val).IsLess(exp)Less than
assert_that(val).is_between(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
assert_that(val).is_equal_approx(exp, margin)AssertThat(val).IsEqualApprox(exp, margin)Float within margin
await assert_signal(mon).is_emitted("name")await AssertSignal(node).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 assert_almost_eq / IsEqualApprox 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 (GUT test_*.gd; gdUnit4 *_test.gd / *Test.cs)
  • Tests extend the correct base class (GutTest / GdUnitTestSuite); C# gdUnit4 suites are plain [TestSuite] classes
  • C#: gdUnit4.api pinned to 4.3.x on Godot 4.3; on 5.x (Godot 4.4+), suites that touch nodes or scenes carry [RequireGodotRuntime]
  • Nodes added to the scene tree use add_child_autofree or auto_free — never manual queue_free()
  • 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)

Comments

Markdown supported