generated from koka-community/template
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtest.kk
120 lines (107 loc) · 4.92 KB
/
test.kk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*----------------------------------------------------------------------------
Copyright 2024, Koka-Community Authors
Licensed under the MIT License ("The License"). You may not
use this file except in compliance with the License. A copy of the License
can be found in the LICENSE file at the root of this distribution.
----------------------------------------------------------------------------*/
// The test effect
pub effect test
ctl test-expect(v: expect-value<a>): a
pub effect test-scope
val scope-name: string
val indentation: string
fun report-fail(): ()
// An expected value for a test
struct expect-value<a>
run-value: error<a> // The value of the computation when run
expect-value: a // The expected value
details: maybe<string> // An additional error message providing context of the expectation
econtinue: bool // Whether to continue with the expected value
location: string // The line where the expectation was made
eq: (a,a) -> pure bool // The equality function for the value
show: (a) -> pure string; // The show function for the value
// Expects a computation to return a value
//
// The expected type must have an `(==)` function as well as a `show` function defined for it
pub fun expect(expected: a, run: () -> <exn,test|e> a, details: string = "", econtinue=True, ?(==): (a,a) -> pure bool, ?show: (a) -> pure string, ?kk-line: string, ?kk-module: string): <test|e> a
val res = try({run()})
test-expect(Expect-value(
res,
expected,
if details == "" then Nothing else Just(details),
True,
?kk-module ++ ":" ++ ?kk-line,
(==), show))
pub fun expect-fail(expected: a, run: () -> <exn,test|e> a, details: string = "", econtinue=False, ?(==): (a,a) -> pure bool, ?show: (a) -> pure string, ?kk-line: string, ?kk-module: string): <test|e> ()
expect(expected, run, details, econtinue)
()
pub fun basic/test(name: string, f: () -> <test,test-scope,console,pure|e> (), ?kk-module: string, ?kk-line: string): <console,pure|e> ()
basic/scope(
name,
{ test-scoped(name, f) }
,is-test=True
)
fun istest/scope(name: string, is-test: bool, f: () -> <test-scope,console|e> (), ?kk-module: string, ?kk-line: string): <test-scope,console|e> ()
val sname = if is-test then "Test" else "Scope"
println(indentation ++ sname ++ "(" ++ ?kk-module ++ ":" ++ ?kk-line ++ "): " ++ name ++ " ... ")
var anyfail := False
with override
val indentation = indentation ++ " "
val scope-name = name
fun report-fail()
anyfail := True
report-fail()
return(x)
if !anyfail then println("Passed!")
else println("")
f()
pub fun basic/scope(name: string, f: () -> <test-scope,console|e> (), is-test: bool = False, ?kk-module: string, ?kk-line: string): <console|e> ()
val sname = if is-test then "Test" else "Scope"
println(sname ++ "(" ++ ?kk-module ++ ":" ++ ?kk-line ++ "): " ++ name ++ " ... ")
var anyfail := False
with handler
val indentation = " "
val scope-name = name
fun report-fail()
anyfail := True
return(x)
if !anyfail then println("Passed!")
else println("")
mask<local>{f()}
pub fun basic-nested/scope(name: string, f: () -> <test-scope,console|e> (), is-test: bool = False, ?kk-module: string, ?kk-line: string): <test-scope,console|e> ()
istest/scope(name, is-test, f)
pub fun scoped/test(name: string, f: () -> <test,test-scope,console,pure|e> (), ?kk-module: string, ?kk-line: string): <console,test-scope,pure|e> ()
basic-nested/scope(name, {test-scoped(name, f)}, is-test=True)
// Runs a test function and prints the first failure including details or "Passed" if all expectations pass in the test
pub fun test-scoped(name: string, f: () -> <test,test-scope,console,pure|e> (), ?kk-module: string, ?kk-line: string): <console,test-scope,pure|e> ()
with handler
ctl test-expect(v)
val Expect-value(a, b, err, cont, location, eq, showa) = v
match a
Error(e) ->
println(indentation ++ " Expect(" ++ location ++ ") == " ++ b.showa ++ ": threw an exception: " ++ e.exn/show ++ err.map(fn(e1) "\n Details: " ++ e1).default(""))
report-fail()
if cont then resume(b)
else ()
Ok(a') ->
if a'.eq(b) then
resume(a')
else
report-fail()
println(indentation ++ " Expect(" ++ location ++ ") == " ++ b.showa ++ ": but got: " ++ a'.showa ++ err.map(fn(e) "\n Details: " ++ e).default(""))
if cont then resume(b)
else ()
f()
// Some simple examples
fun test-tests()
basic/scope("Basics")
with basic-nested/scope("Another")
scoped/test("Returns continue tests")
val res = expect(1) fn() 2
println("Continued!")
expect-fail(2) fn() 1 + res
expect-fail(2) fn() 1
basic/test("Wrong expect")
expect-fail(1) fn() 2
basic/test("Additional info")
expect-fail(1, {throw("Some error somewhere")}, details="Really expected 1 because I proved it!")