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 ofgdsuite.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 belowA 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 = 10000Activate with --profile:
gdtest test/ --profile ciEnvironment variables
These env vars stand in for a CLI flag:
| Env var | CLI 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-importJUnit 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