Snapshot Testing
Capture serialized values on the first run and detect unexpected changes on every run after.
Your SaveGame system serialises the hero's state to a Dictionary. One day someone adds a field, removes one, or changes a key name. The save is now silently incompatible with existing files. A snapshot test catches this the moment the output changes.
How it works
Call assert_snapshot(value) in your test. The first time it runs, gdtest writes the serialized value to a .gdsnap file and the test passes. Every subsequent run compares the current value against that stored file. If they differ, the test fails with a diff.
# test/test_save_game.gd
extends GdTest
func test_hero_save_format() -> void:
var hero = Hero.new()
hero.name = "Aria"
hero.hp = 80
hero.xp = 120
hero.inventory = ["sword", "potion"]
assert_snapshot(SaveGame.serialize(hero))First run — snapshot created, test passes:
✓ test/test_save_game.gd :: test_hero_save_format (18 µs)After a change that removes "inventory" from the output — test fails with a diff:
✗ test/test_save_game.gd :: test_hero_save_format
→ snapshot mismatch 'test_hero_save_format/0':
stored: {"hp":80,"inventory":["sword","potion"],"name":"Aria","xp":120}
actual: {"hp":80,"name":"Aria","xp":120}
(run with --update-snapshots to accept)Multiple snapshots in one test
Pass a name when a single test function captures more than one snapshot:
func test_save_stages() -> void:
var hero = Hero.new()
hero.hp = 100
assert_snapshot(SaveGame.serialize(hero), "initial")
hero.hp = 50
hero.inventory.append("shield")
assert_snapshot(SaveGame.serialize(hero), "after_battle")Names must be unique within the test function. Omit the name to use an auto-incrementing index ("0", "1", …).
Where snapshot files live
Snapshots are stored next to their test file in a __snapshots__/ subdirectory:
test/
├── test_save_game.gd
└── __snapshots__/
└── test_save_game/
├── test_hero_save_format/
│ └── 0.gdsnap
└── test_save_stages/
├── initial.gdsnap
└── after_battle.gdsnapCommit the __snapshots__/ directory. The files are plain text — diffs are human-readable in code review.
Updating snapshots
When you intentionally change a serialized value (adding a field, renaming a key), update the stored snapshots to match:
gdtest test/ --update-snapshotsThis rewrites every .gdsnap file with the current output. Run it once after an intentional change, review the diff in git, then commit.
Supported types
Values are serialized with GDScript's var_to_str(). Supported types include int, float, String, bool, null, Array, Dictionary, Vector2, Vector3, Vector4, Color, Rect2, and most Godot built-in value types.