Add a test framework (GUT) and cover seed determinism and coordinate invariants #12
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
There is no test framework. Verification so far has been throwaway
SceneTreeharnesses written, run, and deleted for each change. That worked for one-off checks, but several properties are cheap to break and silent when broken, and deserve permanent assertions.Framework
GUT (Godot Unit Test) is the recommended choice — it is the established GDScript option, has a CLI runner suited to this workflow, and CLAUDE.md already names it as the intended framework. Install into
addons/gut/via the AssetLib or a git checkout, and enable the plugin.GdUnit4 is the main alternative if GUT proves awkward; it has richer assertions and a scene-runner, at the cost of a heavier install. Not worth switching to speculatively.
Command line runner, roughly:
Logic tests run fine headless. Only visual verification needs a headed run, because
gl_compatibilityrenders nothing headless — that distinction should be recorded so nobody concludes the test suite covers rendering.What to test first
Ordered by "how quietly would this break".
_levels; a different seed produces different ones. This underpins the whole terrain and threat-cycle design, and a break looks exactly like normal operation.main_menu.gd: empty → random, valid integer → literal, anything else →hash(). Both entry paths (button and Enter) must agree. A real bug shipped here — the resolved seed was echoed into the field before resolution, so typing a seed and clicking New Game silently used the previous one while pressing Enter honoured it. A test comparing the two paths would have caught it immediately.surface_y(L) == map_to_local(Vector3i(0, L, 0)).y + level_heightworld_to_cell(cell_to_world(c)) == cfor every cellKnown wrinkles to check during setup
class_nameregistration needs an editor scan (--headless --editor --quit) before a plain headless run can resolve the type.TerrainGridandTerrainPresetare both affected. If the runner is invoked without that, tests fail to parse rather than fail to pass — a confusing first experience.-sharnesses, referencingGameStatedirectly failed to compile and neededroot.get_node("GameState"). GUT's runner is itself invoked with-s, so confirm whether test scripts can reference autoloads by name; if not, tests touchingGameStateneed the same workaround, and that belongs in the test README.Follow-on
Once a real command exists, update CLAUDE.md — it currently says none exists and instructs not to fabricate one. CI is out of scope here; there is no pipeline yet.
Framework is in place and seed determinism is covered as of #15. The remaining items from this issue - seed resolution in
main_menu.gd, the coordinate invariants, and per-preset shape characteristics - are carried over to #16, along with the island-at-small-grid-size finding the new tests surfaced.Closing: "add a test framework" is done; what is left is extending coverage, which is ongoing work rather than a setup task.