A gleeunit compatible test runner for Gleam.
- Watch mode
- JSON, XML and Teamcity outputs
- Failures due to todo in code are a special category
- Skip support with todo in test code
- Process isolation and parallel execution for erlang target
- Test Filtering
- Human readable assert messages
gleam add --dev vouch
// test/my_project_test.gleam -import gleeunit +import vouch pub fn main() { - gleeunit.main() + vouch.main() }
Tests are discovered by the same heuristics that gleeunit uses, with tests as module_tests.gleam, and the usual conventions.
Use let assert, or another assert based assertion library to assert. Vouch formats assert failures in
the most human-friendly way I could manage.
gleam test gleam test -- --filter=parser gleam test -- --test-name-filter=parser # alias for --filter for startest compatibility ( zed extension convention ) gleam test -- --format=json gleam test -- --format=teamcity gleam test -- --junit=report.xml gleam test -- --timeout=1000 # Erlang target only gleam test -- --parallel # Erlang target only gleam test -- --show-crash-reports # Erlang target only, see below gleam test -- --keep-leaked-processes # Erlang target only, see below gleam test -- --color=never # console colour: auto | always | never gleam run -m vouch -- watch # rerun the suite on file change
gleam run -m vouch -- watch [options] reruns the suite whenever there are changes in src/,
test/, or gleam.toml. It works on both targets, and the inner test runs follow the watcher's
own target — so gleam run --target javascript -m vouch -- watch watches JavaScript tests
without the BEAM installed. To run the watcher and the tests on different targets, pass
--target=erlang|javascript after the --; it applies to the inner runs:
gleam run -m vouch -- watch --target=javascript supervises JavaScript tests from the BEAM.
The inner target can also be changed while watching. The hotkeys: j: switch to JavaScript, l: switch to Erlang,
k: switch between the two.
- Erlang: press the key then Enter —
q+ Enter quits,j/l/k+ Enter pick the target. It's a bit awkward, but Ctrl+C is captured by the BEAM and I couldn't get it to work properly. - JavaScript: the usual Jest/Vitest watch keys, single keypress:
Enterforces a rerun,aruns the whole suite (the same thing until test filtering exists),j/l/k: switch inner target, andqor Ctrl+C quits.
The test count changes between targets as you would expect if you have target specific tests.
On Deno, watch mode needs allow_run = ["gleam"].
| Outcome | Meaning | Exit code contribution |
|---|---|---|
| pass | ran without panic | 0 |
| fail | assert/panic/crash/timeout, or a process the test started crashed | 1 |
| todo | hit todo in code under test (directly or in a process it started) |
1 — unimplemented is still not done |
| skip | todo within test function |
0 |
A process that crashes fails the test:
playground_test.background_job_test
Background process crashed at src/playground.gleam:26
background job crashed: queue is full
There is a process leak detector. This does not fail the run.
You can keep leaked processes alive by passing --keep-leaked-processes and they will be left running.
They will still be reported in the summary.
Erlang target supports --parallel, --timeout=n, --show-crash-reports and
--keep-leaked-processes
Deno needs permissions in your project's gleam.toml.
You need allow_read for discovery and source quoting.
you need allow_write if you use --junit for XML report output
You need allow_env for detecting NO_COLOR environemnt variable
You need allow_run if you use watch mode, which spawns gleam test for each cycle
[javascript.deno] allow_read = ["gleam.toml", "src", "test", "build"] allow_write = ["."] allow_env = ["NO_COLOR"] allow_run = ["gleam"]