Skip to main content

Testing

Stof has a thin testing layer built in, alongside run#[test] marks a function as a test, and it always runs as its own separate async process.

Test Functions

The assert family — assert, assert_eq, assert_not, assert_neq — comes from the standard library and throws the moment a check fails:

passes.stof
#[test]
fn passes() {
  assert(true);
  assert_eq("hi", "hi");
  assert_not(false);
  assert_neq("hi", 42);
  pln("all assertions passed");
}
Output

This example calls passes() directly rather than using #[main], since #[test] functions aren't meant to run that way — they're picked up by a different command entirely, covered below.

Note: #[test] functions (scopes & imports, too) are not included in the default prod parse profile, so you'll have to change to test when running embedded, outside of the CLI stof test command.

Expecting a Failure

Add #[errors] alongside #[test] when a test is supposed to throw — the CLI's test runner treats that throw as a pass, not a failure:

fails.stof
#[test]
#[errors]
fn fails() {
  throw("this is an expected error");
}
Output

The playground can't replicate that CLI-level interpretation — calling fails() here just shows the throw itself, which is exactly what #[errors] expects to happen. Whether that throw counts as a pass or a failure is a judgment the stof test command makes, not something visible from the function alone.

Running Tests

stof test replaces stof run at the command line, and reports each test's pass/fail individually, with a small stack trace on anything that failed unexpectedly.