test.oak
← Standard library
See on GitHub ↗
{
default: default
map: map
each: each
every: every
filter: filter
} := import('std')
{
split: split
join: join
} := import('str')
{
printf: printf
} := import('fmt')
debug := import('debug')
fn new(title) {
Tests := []
Skipped := []
fn red(s) '[0;31m' + s + '[0;0m'
fn green(s) '[0;32m' + s + '[0;0m'
fn reportTests(tests) {
tests |> each(fn(test) {
{
name: name
passed?: p?
result: result
expect: expect
} := test
printf(
' {{ 0 }} {{ 1 }}'
if p? {
true -> green('✔')
_ -> red('✘')
}
name
)
fn printIndentedDebug(x, indent) {
debug.inspect(x) |>
split('\n') |>
map(fn(line, i) if i { 0 -> line, _ -> indent + line }) |>
join('\n')
}
if !p? -> {
printf('\texpected: {{ 0 }}', printIndentedDebug(expect, '\t '))
printf('\t result: {{ 0 }}', printIndentedDebug(result, '\t '))
}
})
}
fn reportAggregate {
failedTests := Tests |> filter(fn(t) !t.passed?)
if len(failedTests) {
0 -> printf('All {{ 0 }} tests passed.', len(Tests))
_ -> printf('{{ 0 }} / {{ 1 }} tests passed.', len(Tests) - len(failedTests), len(Tests))
}
if skipped := len(Skipped) {
0 -> ?
_ -> printf('{{ 0 }} tests skipped.', skipped)
}
}
self := {
eq: fn(name, result, expect) Tests << {
name: name
passed?: result = expect
result: result
expect: expect
}
approx: fn(name, result, expect, epsilon) {
epsilon := epsilon |> default(0.00000001)
fn similar?(a, b) if type(a) {
:list -> a |> every(fn(_, i) similar?(a.(i), b.(i)))
:object -> a |> keys() |> every(fn(k) similar?(a.(k), b.(k)))
_ -> a > b - epsilon & a < b + epsilon
}
Tests << {
name: name
passed?: similar?(result, expect)
result: result
expect: expect
}
}
assert: fn(name, result) self.eq(name, result, true)
skip: fn(name, result, expect) Skipped << { name: name }
reportFailed: fn {
if failedTests := Tests |> filter(fn(t) !t.passed?) {
[] -> ?
_ -> {
printf('Failed {{ 0 }} tests:', title)
failedTests |> reportTests()
}
}
reportAggregate()
}
report: fn {
printf('{{ 0 }} tests:', title)
Tests |> reportTests()
reportAggregate()
}
exit: fn {
exit(if Tests |> filter(fn(t) !t.passed?) {
[] -> 0
_ -> 1
})
}
}
}