OxL Reference

Tests

A test is a declaration test "name" { … } next to the code or in the tests/ directory. oxl test builds and runs them in parallel (§18.1). Assertions: assert cond, assert_eq(a, b) / assert_ne (print both sides), assert_fails(expression, ErrorType), assert_snapshot.

oxl✓ checked in CI
fn clamp(x: i32, lo: i32, hi: i32) -> i32 pure => if x < lo { lo } else if x > hi { hi } else { x }

test "clamp keeps values inside the range" {
  assert_eq(clamp(5, 0, 10), 5)
  assert_eq(clamp(-3, 0, 10), 0)
  assert_eq(clamp(99, 0, 10), 10)
}

fixture numbers() -> List<i32> {
  yield [1, 2, 3]
}

test "fixtures give a value to the test" with numbers as xs {
  assert_eq(xs.len(), 3)
}

Replacing services: mock#

mock S { method(patterns) => answer … } replaces a service for the duration of a test; answers are given in order (once, times n, always), fail … returns an error, and S.calls(.method) records the calls with their arguments and context (§18.3).

oxl✓ checked in CI
@error data Declined { reason: str }
data Receipt { id: i64 }

service Payments {
  @public rpc charge(amount: i64) -> Receipt | Declined
}

impl Payments {
  rpc charge(amount) { Receipt{ id: 0 } }
}

test "fail once, then the last response repeats" {
  mock Payments {
    charge(_) => fail Timeout once, then Receipt{ id: 1 }
  }
  assert Payments.charge(10) is Timeout
  assert Payments.charge(10) is Receipt
  assert Payments.charge(10) is Receipt
  assert_eq(Payments.calls(.charge).count, 3)
}

Kinds of tests#

DeclarationWhat it isRun with
test "…"unit test, one node in the processoxl test
test integ "…" with cluster(nodes: 3)a real cluster of processesoxl test --kind integ
test sim "…" seeds 1..=300deterministic simulation: virtual clock and network, node crashes, one run per seedoxl test --kind sim, --seed 7 replays one seed
test ab "…", bench, fuzz, contractA/B experiments, benchmarks, fuzzing, schema checks--kind ab…

A simulation is reproducible: the result depends only on the seed, and a failing seed is printed with the command to replay it. The clock is virtual, so an hour passes instantly (§18.4):

oxl✓ checked in CI
use std.test { clock }
use std.time { sleep, now }

test sim "an hour passes instantly" seeds 1..=3 {
  let t0 = now()
  clock.advance(1h)
  assert now() - t0 == 1h
  sleep(30m)
  assert now() - t0 == 90m
}

The complete project with all kinds is testing-demo; simulation, network faults and node crashes are in the guide. Filters: -f regex, --exact, -t tag, --failed, --changed; coverage: --coverage (oxl test).

See also

OxL 1.0.0-beta · Documentation version 1.0.0-beta© OxwaldLink · generated from the Standard, the std sources and the guides