Documentation

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.

MatcherPasses 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

FlagWhat 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
--hostOnly what needs no device
--device-onlyOnly device suites
-d, --device <id>Only device suites, on this device
--require-deviceA missing device is an error rather than a skip. What CI passes
--listPrint the matching test ids and exit, running nothing
--jsonOutput as JSON
-u, --updateAccept the current output as the goldens (passed to snap)
-r, --releaseTest the release build instead of debug
--timeout <s>Seconds to wait for a device suite. Default 300
--no-fail-fastRun everything even after a failure
-w, --watchStay 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
In a bare crate with no 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