gdtest

Configuration

gdtest's settings, in gdsuite.toml or gdtest.toml, with profile support.

Where settings live

gdtest reads its settings from one of two places, with the same keys:

  • the [test] section of gdsuite.toml, for a project that uses gdsuite and keeps every tool's settings in one file;
  • gdtest.toml, for a project that uses gdtest alone.

Place the file at your Godot project root (next to project.godot). gdtest looks in the folder it runs from, then in its parents, and stops at the Godot project root. gdtest reads the same file whether it is started by gdsuite test, from a terminal, or from the editor panel.

Keep gdtest's settings in one file. When gdsuite.toml has a [test] section, a gdtest.toml next to it is ignored, with a warning: the two files are not merged.

Priority order: CLI flag > env var > config file > built-in default

gdtest.toml

When godot_exe is not set, gdtest looks for a Godot 4 binary under common command names and install locations.

# gdtest.toml — all fields are optional

godot_exe  = "C:/tools/Godot.exe"   # default: auto-discovered
display_mode = "headless"           # "headless" | "windowed"
harness    = "addons/gdtest/gdtest_worker.gd"  # path to gdtest_worker.gd
jobs       = 4          # parallel workers (default: CPU count)
reporter   = "pretty"   # "pretty" | "tap" | "json" | "junit"
isolation  = "file"     # "file" | "test"
timeout    = 5000       # per-test timeout in ms
timeout_warn = 2000     # slow-test warning threshold in ms (no kill)
fail_fast  = false      # stop after first failure
retries    = 0          # re-run failing tests up to N extra times
include_tags = ["fast"] # only run tests with one of these tags
exclude_tags = ["slow"] # skip tests with any of these tags
include    = ["test/**/*.gd", "**/*.test.gd"]  # discovery globs (these are the defaults)
exclude    = ["test/manual/**"]  # discovery excludes for directory/default scans
plugins    = ["res://test/support/slack_reporter.gd"]  # see below

A profile accepts the same keys except godot_exe, include and plugins.

exclude is for your own folders. Hidden folders (.godot, .git…), addons, folders with a .gdignore, and nested Godot projects are always skipped when walking, so they need no entry.

Profiles

Profiles overlay the base config — useful for CI vs local settings:

# gdtest.toml
harness = "addons/gdtest/gdtest_worker.gd"

[profile.ci]
reporter  = "junit"
fail_fast = true
jobs      = 4
timeout   = 10000

Activate with --profile:

gdtest test/ --profile ci

Environment variables

These env vars stand in for a CLI flag:

Env varCLI flag
GODOT_EXE--godot-exe
GDTEST_HARNESS--harness
GDTEST_JOBS-j
GDTEST_REPORTER--reporter
GDTEST_ISOLATION--isolation
GDTEST_TIMEOUT--timeout
GDTEST_TIMEOUT_WARN--timeout-warn
GDTEST_FAIL_FAST--fail-fast
GDTEST_RETRIES--retries
GDTEST_DISPLAY_MODE--display-mode
GDTEST_INCLUDE_TAGS--tag
GDTEST_EXCLUDE_TAGS--exclude-tag
GDTEST_SEED--seed
GDTEST_COVERAGE_EXCLUDE--coverage-exclude

Plugins

plugins lists GDScript files the worker loads at startup. A plugin extends Gdt.GdtReporter to receive run events, or Gdt.GdtFixture to run code around every suite and test:

# res://test/support/slack_reporter.gd
extends Gdt.GdtReporter

func on_test_fail(file: String, name: String, us: int, failures: Array) -> void:
    print("FAILED %s :: %s" % [file, name])

func on_run_end(passed: int, failed: int, skipped: int) -> void:
    print("%d passed, %d failed" % [passed, failed])

A reporter can also implement on_run_start(total_tests), on_test_start(file, name), on_test_pass(file, name, us), on_test_skip(file, name, message) and on_test_error(file, name, message). A fixture implements any of before_suite(), after_suite(), before_each() and after_each().

CI example (GitHub Actions)

- name: Run gdtest
  run: gdtest test/ --profile ci --no-auto-import

JUnit XML integrates with GitHub's test reporter when piped to a file.

In gdsuite.toml

Every key above goes under [test], and profiles under [test.profile.<name>]:

# gdsuite.toml
[test]
harness = "addons/gdtest/gdtest_worker.gd"
exclude = ["test/helpers/**", "test/mocks/**"]

[test.profile.ci]
reporter = "junit"
fail_fast = true