OxL Reference

tests/shop_test.oxl

oxl
use super.shop { Payments, Receipt, Declined, pay }
use std.test { clock }

// A fixture: the value before `yield` goes to the test, the code after it is the clean-up.
fixture ledger() -> List<str> {
  var entries: List<str> = []
  yield entries
  print("ledger closed")
}

test "a payment under the limit succeeds" {
  assert pay(500) is Receipt
}

test "assert_eq prints both sides on failure" {
  assert_eq(2 + 2, 4)
  assert_ne("a", "b")
}

test "a payment over the limit is declined" {
  assert_fails(pay(200000), Declined)
}

test "fixtures give a fresh value to every test" with ledger as entries {
  assert_eq(entries.len(), 0)
}

test "a timeout is retried once" {
  mock Payments {
    charge(_) => fail Timeout once, then Receipt{ id: 7 }
  }
  let r = pay(100)
  assert r is Receipt
  assert_eq(Payments.calls(.charge).count, 2)
}

test "a mock can script an error" {
  mock Payments { charge(_) => fail Declined{ why: "fraud" } always }
  assert pay(100) is Declined
  assert_eq(Payments.calls(.charge).count, 1)
}

// Simulation: the clock is virtual, so an hour costs nothing; the body runs once per seed.
test sim "an hour passes instantly" seeds 1..=5 {
  let t0 = now()
  clock.advance(1h)
  assert now() - t0 == 1h
  sleep(30m)
  assert now() - t0 == 90m
}

Source: examples/testing-demo/tests/shop_test.oxl