Testing
A test declares an in-language unit test: a named imperative block run against a fresh world by ox test. Its name is a string literal; its body is the mutate-body statement set (mutate) plus the assert statement. An assert mirrors require, except a failed assert records a pass/fail outcome and execution continues (rather than aborting). Three assertion forms exist: the value/boolean form assert <expr>;; the derivability form assert [not] derivable F(args);, which tests membership / non-derivability of a fact against the materialized extent with world-honest three-valued outcomes — present ⇒ PASS/FAIL, absent under closed-world ⇒ FAIL/PASS, absent under open-world ⇒ a loud INCONCLUSIVE (absence is unknown, not false, World assumptions (CWA / OWA)); and the rejection form assert rejects [( Pkg::Code )] { … }, which asserts that a write block is refused by a write-path guard (a where-invariant, a check delta-guard, a group axiom, …) — a genuine guard rejection PASSes (matching a pinned code if given), an accepted write FAILs, and a non-guard error ERRORs loudly so a broken test never masquerades as a passing rejection. derivable and rejects are contextual keywords (leading position only). The runner, the full assertion semantics — including reads over the deductive plane, the three-valued tables, and the guard-vs-non-guard classification — isolation, and the scope are specified in Runtime contract.
test-decl ::= attribute* 'test' String '{' test-stmt* '}'
test-stmt ::= mutate-stmt // `mutate`: let / insert / update / delete / for / require / calls
| 'assert' expr ';'
| 'assert' 'not'? 'derivable' IDENT '(' (expr (',' expr)*)? ')' ';'
| 'assert' 'rejects' ('(' path ')')? '{' mutate-stmt* '}' ';'
(The fixture / expect block forms are reserved and do not parse.)
pub type Account { name: String }
// A test constructs a world top-to-bottom and asserts over it; `ox test`
// runs each test against its own fresh store and reports PASS / FAIL / ERROR.
test "a constructed account carries its name" {
let cash = insert Account { name: "Cash" };
assert cash.name == "Cash";
}
Discovery. ox test runs test declarations from mod-reachable modules and auto-discovers every *.ar anywhere under the package’s tests/ directory (recursive, any depth — so no test under tests/ silently fails to run), elaborating them as part of the package — so a test placed in the reserved tests/ directory runs without mod-wiring, symmetric with scenarios/*.toml. This is test-mode only: tests/*.ar never enters ox build’s artifact. See Runtime contract.
Isolation. Each test runs against its own fresh store seeded with the package’s declared facts; no test sees another’s writes, so test ordering is unspecified and irrelevant. Within a test, the body’s writes are visible to later assertions, including the facts they derive (read-your-writes over the committed + deductive state). See Runtime contract for the ox test runner and the assertion semantics in full.