whitehall test
Run the project's tests — every language, one report.
Usage
whitehall test [target] [options] test runs whatever each language already means by "test": Rust's #[cfg(test)], Zig's test "…" blocks, a *.test.c program, and a fun in a *.test.wh. With nothing plugged in,
everything that does not need a phone runs, and the rest is skipped out loud.
$ whitehall test
Running 47 tests (rust 12, zig 4, c 1, wh 30)
Passed rust 12 on the host
Failed zig 3 of 4 on the host
Failed stores/cart.zig::totals what is in it
expected 7, found 6
--> src/stores/cart.zig Writing a test in .wh
A top-level fun that takes no arguments, in a file named *.test.wh, is a test. There is no attribute and no registration. $expect is the assertion.
// src/lib/greeting.test.wh
fun greeting_names_the_person() {
val greeting = "Hello, " + "Whitehall" + "!"
$expect(greeting).toBe("Hello, Whitehall!")
} whitehall init --app writes this file as src/lib/example.test.wh.
The name has no + because + means the file ships; a test does not.
| Matcher | Passes when |
|---|---|
.toBe(x) | the value equals x |
.notToBe(x) | the value does not equal x |
.toBeTrue(), .toBeFalse() | the value is that boolean |
.toBeNull(), .notToBeNull() | the value is, or is not, null |
.toContain(part) | the string or collection contains part |
.toHaveSize(n) | the collection has n elements, or the string n characters |
A failure points at the .wh line
A failing assertion is reported at the line of your test function in the .wh file, not at a line of generated Kotlin. The message names the values: expected "Hello", got "Hi"-shaped, with strings quoted so a type mismatch reads
as one.
.wh tests run on the host JVM, with no Gradle between a save and a verdict. A
test that touches nothing under android.* runs there: plain Kotlin and Compose
runtime state. A test that reaches an Android Context fails with a message that
says so.
Where the file sits sets the kind. A *.test.wh under src/routes/ or src/components/ mounts something, so it is a render test and needs a device. Anywhere else it is a unit test and runs on
the host.
Watching
whitehall test --watch Run once, then stay running and rerun the tests a saved file touches. A red run is printed and the loop carries on.
Options
| Flag | What it does |
|---|---|
-f, --filter <text> | Only tests whose id contains this |
--lang <x> | Only this language: wh, rust, zig, c, cpp, go. Repeatable |
--kind <x> | Only this kind: unit, render, snap. Repeatable |
--host | Only what needs no device |
--device-only | Only device suites |
-d, --device <id> | Only device suites, on this device |
--require-device | A missing device is an error rather than a skip. What CI passes |
--list | Print the matching test ids and exit, running nothing |
--json | Output as JSON |
-u, --update | Accept the current output as the goldens (passed to snap) |
-r, --release | Test the release build instead of debug |
--timeout <s> | Seconds to wait for a device suite. Default 300 |
--no-fail-fast | Run everything even after a failure |
-w, --watch | Stay running; rerun the tests a saved file touches |
whitehall test --filter cart # tests with "cart" in the id
whitehall test --lang wh --list # which .wh tests would run
whitehall test --require-device # CI: no phone is a failure, not a skip whitehall.toml, whitehall test runs cargo test through the Android context. The flags a crate cannot answer — --json, --update, --kind, --lang other
than rust — are refused by name.See Also
- whitehall snap — golden screenshots, also run as a suite by
test - whitehall bench — on-device benchmarks
- whitehall dev — the edit loop
- All commands