Write a test
Put a test in a file called *.test.trb, by convention under tests/, group related ones, and let assert show the source and the values instead of writing a matcher.
A test is an ordinary function call, test and group from std/test, in a file the compiler runs and nothing
imports. There are no matchers: assert takes the condition itself and reports the source and the values it captured
when it fails.
Steps#
Create a file named
<something>.test.trb, by convention undertests/. The name is what makes it a test, wherever it lies in the package, and a test file may hold top-level code, so it is a script and needs nofn main.my-project/ ├ src/ ├ tests/ ├─ vector2.test.trb └ project.trbImport
testandgroup. Neither is in the prelude, so every test file says so on its first line.use test, group from "std/test"Name a
groupfor the type or the function under test, and atestfor each behaviour. Both take a name and a closure; agroupnests freely, so a suite is organized by nesting one inside another.group "Vector2" { test "adds component-wise" { assert(Vector2(1.0, 2.0).plus(Vector2(3.0, 4.0)) == Vector2(4.0, 6.0)) } }Write the condition as one
assert, not a sequence of them with messages.asserttakes anExpression<Bool>, so a failure already shows the source text of the condition and the values it closed over - there is nothing to add by writing a message.Run the tests with
torb test. Without a path it runs every test of the package the working directory is in; a path runs the ones below it:$ torb test my-project/tests my-project/tests/vector2.test.trb ok Vector2 > adds component-wise 1 passed, 0 failed (1 file)
Pitfalls#
- A test fails by panicking, not by returning a value.
assertpanics on a false condition, and the test runner catches that panic per test - a test function never returns aResultor aBoolfor the runner to check. - Nothing but a
*.test.trbfile, a program's entry, a script or a receiver script may hold top-level code. Test helpers that are more than one file belong in an ordinary module and are imported like any other name. - A test cannot import the program.
src/main.trband theentryof aprogramline are never importable, so what a test calls lives in a module -src/<something>.trb- that the program imports too. assertneeds no message argument to be useful.assert(actual == expected, "should be equal")adds a second argument the failure text does not use; the condition alone already carries the values through the expression tree.- A failing assertion names the location, not a stack. The output is one line for what failed and one for where -
at <path>:<line>:<column>- which is what a search for the exact text of a failure has to match.
Full example#
use test, group from "std/test"
type Vector2 {
x: Float
y: Float
fn plus(other: Vector2): Vector2 {
Vector2(x + other.x, y + other.y)
}
}
group "Vector2" {
test "adds component-wise" {
assert(Vector2(1.0, 2.0).plus(Vector2(3.0, 4.0)) == Vector2(4.0, 6.0))
}
}Related#
- std/test -
testandgroupin full. - std/expression -
assert, and what anExpression<Bool>captures. - Verify your work - where
testfits amongcheckandformat --check. - Top-level code - why a test file needs no
fn main.