The previous tests never compiled: they used GUT's assert functions, Godot 3 APIs and reassigned autoload functions, so no test ran. - 90 tests: unit tests for the playlist, songs, player scoring, time formatting, search and the server client, plus integration tests that run MainWindow and SyncWindow against a fake server - Keybind tests check that Alt+<number> and Ctrl+Alt+<number> keep following the player rows while players are added and removed - run_tests.sh finds Godot and runs the suite headless (~10 seconds) - CI runs the tests before the build job in gitea-build.yaml; the separate test.yml used a GitHub action that does not exist - GdUnit4 is committed instead of ignored, since the project enables it, and .gitea/ is no longer ignored - Exported builds leave out tests/ and addons/gdUnit4/
64 lines
2.6 KiB
Markdown
64 lines
2.6 KiB
Markdown
# 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.
|