Тесты
Тест — объявление test "имя" { … } рядом с кодом или в каталоге tests/. oxl test собирает и запускает их параллельно
(§18.1). Утверждения: assert cond, assert_eq(a, b) / assert_ne (печатают обе стороны), assert_fails(выражение, ТипОшибки),
assert_snapshot.
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)
}
// Фикстура: значение до yield получает тест, код после yield — очистка
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)
}Подмена сервисов: mock#
mock S { метод(образцы) => ответ … } подменяет сервис на время теста; ответы выдаются по порядку (once, times n,
always), fail … возвращает ошибку, S.calls(.метод) записывает вызовы вместе с аргументами и контекстом
(§18.3).
@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)
}Виды тестов#
| Объявление | Что это | Запуск |
|---|---|---|
test "…" | юнит-тест, один узел в процессе | oxl test |
test integ "…" with cluster(nodes: 3) | настоящий кластер из процессов | oxl test --kind integ |
test sim "…" seeds 1..=300 | детерминированная симуляция: виртуальные часы и сеть, падения узлов, по запуску на seed | oxl test --kind sim, --seed 7 — повторить один seed |
test ab "…", bench, fuzz, contract | A/B-эксперименты, бенчмарки, фаззинг, проверка схем | --kind ab… |
Симуляция воспроизводима: результат зависит только от seed, упавший seed печатается с командой повтора. Часы виртуальные — час пролетает мгновенно (§18.4):
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
}Полный проект со всеми видами — testing-demo; подробности симуляции, сетевых сбоев и падений узлов — в
руководстве. Фильтры: -f regex, --exact, -t tag, --failed, --changed; покрытие — --coverage
(oxl test).