//! A simple test library.
let string = import! std.string
let { wrap } = import! std.applicative
let { flat_map } = import! std.monad
let float = import! std.float
let int = import! std.int
let list @ { List, ? } = import! std.list
let { Foldable, foldl } = import! std.foldable
let { Option } = import! std.option
let { Result } = import! std.result
let { Semigroup, (<>) } = import! std.semigroup
let { error } = import! std.prim
let { (>>), id } = import! std.function
let { ? } = import! std.io
let { assert } = import! std.assert
let effect @ { Eff, ? } = import! std.effect
let { Writer, run_writer, tell } = import! std.effect.writer
let { Error, run_error } = import! std.effect.error
let { Lift, run_lift } = import! std.effect.lift
type Test r a = Writer (List String) r a
type TestEff r a = Eff [| writer : Test | r |] a
type TestEffIO r a = Eff [| writer : Test, lift : Lift IO | r |] a
type TestCase r a =
| Test String (() -> Eff [| writer : Test | r |] a)
| Group String (Array (TestCase r a))
let test = Test
let group = Group
let assert_eq l r : [Show a] -> [Eq a] -> a -> a -> Eff [| writer : Test | r |] () =
if l == r then wrap ()
else tell (Cons ("Assertion failed: " <> show l <> " != " <> show r) Nil)
let assert_neq l r : [Show a] -> [Eq a] -> a -> a -> Eff [| writer : Test | r |] () =
if l /= r then wrap ()
else tell (Cons ("Assertion failed: " <> show l <> " == " <> show r) Nil)
let assert_lt l r : [Show a] -> [Ord a] -> a -> a -> Eff [| writer : Test | r |] () =
if l < r then wrap ()
else tell (Cons ("Assertion failed: " <> show l <> " >= " <> show r) Nil)
let assert_lte l r : [Show a] -> [Ord a] -> a -> a -> Eff [| writer : Test | r |] () =
if l <= r then wrap ()
else tell (Cons ("Assertion failed: " <> show l <> " > " <> show r) Nil)
let assert_gt l r : [Show a] -> [Ord a] -> a -> a -> Eff [| writer : Test | r |] () =
if l > r then wrap ()
else tell (Cons ("Assertion failed: " <> show l <> " <= " <> show r) Nil)
let assert_gte l r : [Show a] -> [Ord a] -> a -> a -> Eff [| writer : Test | r |] () =
if l >= r then wrap ()
else tell (Cons ("Assertion failed: " <> show l <> " < " <> show r) Nil)
let assert_ok res : [Show e] -> Result e a -> Eff [| writer : Test | r |] () =
match res with
| Ok _ -> wrap ()
| Err e -> tell (Cons ("Assertion failed: found error: " <> show e) Nil)
let assert_err res : [Show a] -> Result e a -> Eff [| writer : Test | r |] () =
match res with
| Ok x -> tell (Cons ("Assertion failed: expected error, found " <> show x) Nil)
| Err _ -> wrap ()
let assert_success : [Show e]
-> Eff [| error : Error e, writer : Test | r |] a
-> Eff [| writer : Test | r |] ()
=
run_error >> flat_map assert_ok
let assert_throws : forall e .
[Show a] -> Eff [| error : Error e, writer : Test | r |] a -> Eff [| writer : Test | r |] ()
=
run_error
>> flat_map assert_err
rec let run_raw test : Eff [| writer : Test | r |] a -> Eff [| | r |] (List String) =
do test = run_writer test
wrap test.writer
in
rec let run test : Eff [| writer : Test | r |] a -> Eff [| | r |] () =
do writer = run_raw test
match writer with
| Cons _ _ -> error (foldl (\acc err -> acc <> "\n" <> err) "" writer)
| Nil -> wrap ()
in
rec let run_io test : TestEffIO r a -> IO () =
run_lift (run test)
{
Test,
TestEff,
TestEffIO,
TestCase,
test,
group,
assert,
assert_eq,
assert_neq,
assert_lt,
assert_lte,
assert_gt,
assert_gte,
assert_ok,
assert_err,
assert_success,
assert_throws,
run_raw,
run,
run_io,
}