21Testing
Cryo ships a built-in unit-test framework. Tests live in <project>/tests/ files whose namespace declaration carries the ![config(testing)] directive. Inside such a file, every function marked ![test] is auto-discovered by the compiler and run fork-per-test by cryo test.
![config(testing)]
namespace MyApp::Tests;
import std::test::assert::{ expect_eq, expect, bail };
![test]
function addition_is_commutative() -> Result<(), TestError> {
return expect_eq(1 + 2, 2 + 1);
}
![test]
![ignore]
function expensive_integration_test() -> Result<(), TestError> {
// Run only when the user passes --ignored.
return expect(setup_real_environment(), "environment ready");
}
![test]
![should_panic]
function unwrap_none_panics() -> Result<(), TestError> {
const empty: Option<int> = Option::None;
const _value: int = empty.unwrap(); // panics
return bail("unwrap should have panicked");
}
A test function returns Result<(), TestError>. Ok(()) is success; Err(...) is failure with a message. The assert module provides:
expect(condition, message): fails if the condition is false.expect_eq(a, b): fails ifa != b(requiresT: Eq + Display).expect_ne(a, b): fails ifa == b.bail(message): unconditional failure.bail_other(message): non-assertion failure (treated as an error rather than a test fail).
The runner forks a child process per test, captures its output, and applies the ![should_panic] inversion if requested. Run with:
cryo test # run every discoverable test
cryo test some_filter # run tests whose name contains "some_filter"
cryo test --list # discover only; print and exit
cryo test --ignored # also run ![ignore]-marked tests
cryo test --exact # treat the filter as an exact match
cryo test -q, --quiet # suppress per-test ok / ignored lines
Output format
The runner ships three output formats; --format=<mode> picks per-run:
| Format | Layout |
|---|---|
plain | Cargo-style test NAME ... ok lines; CI-friendly. Default. |
pretty | Tests grouped under their namespace, indented leaves, [PASS] / [FAIL] / [skip] chips. Colored on a TTY. |
compact | One line per namespace with a dot-stream of results (. pass, F fail, s skip, P did-not-panic, E runner error) and a trailing per-group tally. |
Color follows --color=<auto|always|never>. auto (default) emits ANSI escapes only when stdout is a terminal; the NO_COLOR environment variable forces it off per https://no-color.org/.
Configuration precedence is CLI flag > environment variable > cryoconfig > built-in default:
cryo test --format=pretty --color=always
CRYO_TEST_FORMAT=compact CRYO_TEST_COLOR=never cryo test
# cryoconfig
[test]
format = "pretty" # one of: plain | pretty | compact
color = "auto" # one of: auto | always | never
cryo test forwards [test] format = "..." to the spawned test binary as --format=..., so the cryoconfig defaults travel without needing exported environment variables.