Every popup is now called *Popup instead of *Window in its file, root node, node name, class and variable, and PopupWindow becomes BasePopup. Player is PlayerRow, SongListObject is SongRow and Character is CharacterCard. Script files are snake_case and scene files PascalCase, each matching its class or root node, and LightGrayTheme.tres is light_gray_theme.tres.
2.6 KiB
Testing
Tests use GdUnit4 6.2.1, committed in
addons/gdUnit4/. The whole suite runs headless in about 10 seconds.
Running the tests
./run_tests.sh # everything
./run_tests.sh res://tests/unit # only unit tests
./run_tests.sh res://tests/unit/test_search.gd # one suite
The script finds Godot through $GODOT, then godot on your PATH, then
/Applications/Godot.app or /Applications/Godot_mono.app. Reports are written to
reports/ (ignored by git).
In the editor, open the GdUnit4 panel or right-click the tests folder and choose
Run Tests.
CI runs the suite in the test job of .gitea/workflows/gitea-build.yaml on every push
and pull request to main and develop. The build job only starts once the tests
pass.
Layout
| Folder | Contents |
|---|---|
tests/unit/ |
Logic without scenes: playlist, songs, player scoring, time formatting, search, the server client |
tests/integration/ |
Real scenes (MainWindow.tscn, SyncPopup.tscn) run against a fake server, including the point keybinds |
tests/fakes/ |
FakeHttpTransport, AutoloadSnapshot and the MainWindowTestSuite base class |
tests/data/ |
Files the fake server sends, e.g. a short MP3 |
Faking the MusicServer
All server calls go through the MusicServerClient autoload, which sends requests with
a swappable transport. Tests install a FakeHttpTransport that answers from canned
responses and records what was requested:
var server: FakeHttpTransport = FakeHttpTransport.new().install()
server.respond_json("/music/list", [{"SongNo": 0, "Soundtrack": "Chrono Trigger", "Song": "Frog's Theme"}])
server.respond_bytes("/music/rand", mp3_bytes)
# ... run the code under test ...
assert_int(server.count("/music/rand")).is_equal(1)
server.uninstall()
Paths without a response get a 404, so the code under test sees a failed request.
Writing tests
- Settings and Playlist are global. Tests that change them restore them afterwards, either
by hand or with
AutoloadSnapshot.take([Settings, Playlist])andrestore(). - Main window tests extend
MainWindowTestSuite, which starts the window against the fake server and has helpers such as_add_player(),_remove_player()and_give_point_with_keybind(). - Player ids are UUID strings that never change. A player's position in
Settings.player_arrayonly decides their keybind (Alt+1 for the first row and so on), so tests check both: that points land on the right player id, and that keybinds follow the rows when players are added or removed.