Railroad
An advanced testing library and test runner for Standard ML, highly inspired by elm-test and Expecto.
This library provides a set of composable functions for writing tests, along with a built-in test runner.
Installation
$ git clone https://github.com/PerplexSystems/Railroad.git $YOUR_PROJECT/vendor/Railroad
Then reference vendor/Railroad/sources.mlb
on your project’s .mlb
file. Example:
$(SML_LIB)/basis/basis.mlb
lib/Railroad/sources.mlb
main.sml
Usage
val tests =
describe "math operations"
[ test "sum 1 + 1" (fn _ =>
Expect.equal Int.compare 2 (1 + 1))
]
val _ =
run tests
Check out the table of contents below for more information:
API Reference
Test
The Test
module consists of functions that are involved in
creating and managing tests.
concat
val concat: Test list -> Test
Concatenates a list of tests.
concat [ userTests, baggageTests ]
describe
val describe: string -> Test list -> Test
Describes a list of tests.
describe "math operators"
[ test "sum" (fn _ =>
Expect.equal Int.compare 2 (1 + 1))
, test "failing sum" (fn _ =>
Expect.equal Int.compare 3 (2 + 3))
]
focus
val focus: Test -> Test
Returns a Test
that causes other tests to be skipped, and
only runs the given one.
Calls to focus
aren’t meant to be committed to version
control. Instead, use them when you want to focus on getting a
particular subset of your tests to pass. If you use focus
, your
entire test suite will fail, even if each of the individual tests
pass. This is to help avoid accidentally committing a focus
to
version control.
If you you use focus
on multiple tests, only those tests will run.
If you put a focus
inside another focus
, only the outermost only
will affect which tests gets run.
See also skip
. Note that skip
takes precedence over
focus
; if you use a skip
inside a focus
, it will still get
skipped, and if you use a focus
inside a skip
, it will also get
skipped.
describe "math operators"
[ test "sum" (fn _ =>
Expect.equal Int.compare 2 (1 + 1))
, focus (test "this is the only test that will run" (fn _ =>
Expect.equal Int.compare 3 (2 + 3)))
]
run
runwithoptions
skip
val skip: Test -> Test
Returns a Test
that gets skipped.
Calls to skip
aren’t meant to be committed to version
control. Instead, use it when you want to focus on getting a
particular subset of your tests to pass. If you use skip
, your
entire test suite will fail, even if each of the individual tests
pass. This is to help avoid accidentally committing a skip to version
control.
See also focus
. Note that skip
takes precedence over
focus
; if you use a skip
inside a focus
, it will still get
skipped, and if you use a focus
inside a skip
, it will also get
skipped.
describe "math operators"
[ test "this test will be the only one to run" (fn _ =>
Expect.equal Int.compare 2 (1 + 1))
, skip (test "this test is skipped" (fn _ =>
Expect.equal Int.compare 3 (2 + 3)))
]
test
val test: string -> (unit -> Expectation) -> Test
Return a Test
that evaluates a single Expectation
.
test "sum" (fn _ => Expect.equal Int.compare 2 (1 + 1))
Expect
The Expect
module consists of assertion functions that
describes a claim to be tested.
actual
type 'a actual = 'a
Represents the actual value passed to an assertion function.
expected
type 'a expected = 'a
Represents the expected value passed to an assertion function.
comparer
type 'a comparer = ('a expected * 'a actual) -> General.order
Represents a function that compares the expected
against the actual
value.
tostring
type 'a tostring = 'a -> string
Represents a function that converts the given value to a string
.
pass
val pass: Expectation
Always passes.
test "this sum is always two" (fn _ =>
if (1 + 1) = 2 then
Expect.pass
else
Expect.fail "man, something is up...")
fail
val fail: string -> Expectation
Always fails.
test "this sum is always two" (fn _ =>
if (1 + 1) = 2 then
Expect.pass
else
Expect.fail "man, something is up...")
onfail
val onfail: string -> Expectation -> Expectation
If the given expectation fails, replace its failure message with a custom one.
test "sum" (fn _ =>
Expect.onfail
"this shouldn't be failing"
(Expect.equal Int.compare 4 (2 + 2)))
istrue
val istrue: bool actual -> Expectation
Passes if the provided value is true
.
Expect.istrue (2 > 1)
isfalse
val isfalse: bool actual -> Expectation
Passes if the provided value is false
.
Expect.istrue (2 < 1)
some
val some: 'a option actual -> Expectation
Passes if the provided value is SOME
.
val value = SOME 1
Expect.some value
none
val none: 'a option actual -> Expectation
Passes if the provided value is NONE
.
val value = NONE
Expect.none value
equal
val equal: 'a comparer -> 'a expected -> 'a actual -> Expectation
Passes if the arguments are equal.
Expect.equal Int.compare 2 (1 + 1)
equalfmt
val equalfmt: 'a comparer -> 'a tostring -> 'a expected -> 'a actual -> Expectation
Passes if the arguments are equal, but receives a
tostring
that encapsulates the values on the
Expectation
.
Expect.equalfmt Int.compare Int.toString 2 (1 + 1)
notequal
val notequal: 'a comparer -> 'a expected -> 'a actual -> Expectation
Passes if the arguments are not equal.
Expect.notequal Int.compare 3 (1 + 1)
notequalfmt
val notequalfmt: 'a comparer -> 'a tostring -> 'a expected -> 'a actual -> Expectation
Passes if the arguments are not equal, but receives a
tostring
that encapsulates the values on the
Expectation
.
Expect.equalfmt Int.compare Int.toString 2 (1 + 1)
atmost
val atmost: 'a comparer -> 'a expected -> 'a actual -> Expectation
Passes if the provide value is less or equal than the expected value.
Expect.atmost Int.compare 3 2
Expect.atmost Int.compare 2 2
atmostfmt
val atmostfmt: 'a comparer -> 'a tostring-> 'a expected-> 'a actual-> Expectation
Passes if the provided value is less or equal than the expeted value,
but receives a tostring
that encapsulates the values on
the Expectation
.
Expect.atmost Int.compare Int.toString 3 2
Expect.atmost Int.compare Int.toString 2 2
atleast
val atleast: 'a comparer -> 'a expected -> 'a actual -> Expectation
Passes if the provide value is greater or equal than the expected value.
Expect.atmost Int.compare 3 4
Expect.atmost Int.compare 3 3
atleastfmt
val atleastfmt: 'a comparer -> 'a tostring -> 'a expected -> 'a actual -> Expectation
Passes if the provided value is greater or equal than the expeted
value, but receives a tostring
that encapsulates the
values on the Expectation
.
Expect.atmost Int.compare Int.toString 3 4
Expect.atmost Int.compare Int.toString 3 3
less
val less: 'a comparer -> 'a expected -> 'a actual -> Expectation
Passes if the provided value is less than the expected value.
Expect.notequal Int.compare 3 (1 + 1)
lessfmt
val lessfmt: 'a comparer -> 'a tostring -> 'a expected -> 'a actual -> Expectation
Passes if the provided value is less than the expeted value, but
receives a tostring
that encapsulates the values on the
Expectation
.
Expect.atmost Int.compare Int.toString 3 2
greater
val greater: 'a comparer -> 'a expected -> 'a actual -> Expectation
Passes if the provided value is greater than the expected value.
Expect.notequal Int.compare 3 4
greaterfmt
val greaterfmt: 'a comparer -> 'a tostring -> 'a expected -> 'a actual -> Expectation
Passes if the provided value is greater than the expeted value, but
receives a tostring
that encapsulates the values on the
Expectation
.
Expect.atmost Int.compare Int.toString 3 4