Skip to content

Testing (Headless)

Plume3D can run an app’s Wren test suite headless — no window, no Vulkan surface, no render loop — and exit with a process code the suite controls. This is how a game’s Wren logic is gated in CI, and it works on machines with no display.

Terminal window
plume3d --test <appdir> # alias: --headless ; also --test=<appdir>
  • Mounts <appdir> and loads <appdir>/tests/run.wren.
  • Calls the static method Tests.main().
  • Exits with the code set by Engine.exit(code) (default 0).

The --test path returns before any window or renderer is created, so renderer/audio/window-dependent API calls are inert in this mode — keep test suites to game logic. game.toml is not required for --test.

Create <appdir>/tests/run.wren:

import "engine" for Engine
// import your game modules and assertions here…
class Tests {
static main() {
// run assertions; on failure call Engine.exit(1)
Engine.exit(0) // 0 = suite passed
}
}

Tests.main() is the whole contract — structure your suite however you like inside it (many apps build a small assert/test framework in Wren and call it from here).

Prefer calling Engine.exit as the final action of the suite: Engine.exit is record-and-honor, so code after it still runs — and a Wren runtime error always wins over a recorded Engine.exit(0) (a crashing suite can never report green).

CodeMeaning
value of Engine.exit(code)Whatever the suite requested (clamped 0–255). Wins, except a Wren error after a recorded Engine.exit(0) still yields 1.
0Tests.main() returned cleanly without calling Engine.exit (or called Engine.exit(0) and did not error).
1tests/run.wren failed to compile, has no Tests class, or Tests.main() raised a Wren runtime error — and no explicit non-zero Engine.exit was requested.
2Setup error: app dir missing (or no app dir given), tests/run.wren missing/unreadable, mount failure, or --test combined with --tool.
70Filesystem initialization failed.
Terminal window
# fails the job if any Wren assertion fails
plume3d --test apps/mygame || exit $?

Pair headless testing with the seeded Random API: construct generators from fixed seeds so test runs are deterministic across machines and platforms.


See Engine.exit for exit semantics in normal (windowed) runs, and Getting Started for the app layout.