# Testing Tests use [GdUnit4](https://github.com/godot-gdunit-labs/gdUnit4) 6.2.1, committed in `addons/gdUnit4/`. The whole suite runs headless in about 10 seconds. ## Running the tests ```bash ./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`, `SyncWindow.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: ```gdscript 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])` and `restore()`. - 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_array` only 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.