std/test
Tests, which cuarzo test runs. A test file is a file whose name ends in
_test.cz; its tests are the functions whose names start with test_ and
that take nothing:
// shapes_test.cz
import "std/test"
import "shapes"
func test_area() do
assert_equal(area(2, 3), 6)
endcuarzo test every *_test.cz file under this folder,
or in a project, those its cuarzo.toml names
cuarzo test shapes_test.cz tests/ these files and foldersA test passes unless an assertion fails, it panics, or it stops with a
runtime error; a test that brings its program down fails with what the
program printed. Each test file is built into a program of its own (in
build/tests beside it), and the programs run side by side.
| Option | |
|---|---|
--filter <text> |
only the tests whose names, or file::name, hold the text |
-j <n> |
how many test programs run at once (4) |
--bench |
run the benchmarks instead of the tests |
--coverage |
count the lines that run, and report them for each file of the program, with build/coverage.lcov |
--update-snapshots |
take the snapshots again |
--json |
results as JSON lines, one for each test, for editors |
--junit <file.xml> |
results as JUnit XML too, for CI |
--profile <name>, --release |
in a project, the profile to build the tests with; debug otherwise |
Assertions
| Function | Fails unless |
|---|---|
assert_equal(actual, expected) |
they are equal; text of several lines shows the lines that differ |
assert_not_equal(actual, other) |
they differ |
assert_true(value), assert_false(value) |
|
assert_items(actual, expected) |
two arrays have equal items, in order; says which differ |
assert_contains(text, part) |
|
assert_ok(result) |
a Result is OK, and gives what it holds |
assert_error(result) |
a Result is an ERROR, and gives the error |
assert_panics(body) |
calling body panics, and gives the message |
assert_fail(message) |
never: it fails the test at once |
Each takes a message last, to say what was checked.
Setup, async tests, and benchmarks
setup() and teardown(), when a test file has them, run before and after
each test. An async func test_...() is a test on the event loop: it
passes when its task settles OK. A function whose name starts with
bench_ is a benchmark, which cuarzo test --bench runs in rounds for
about a second, reporting the time of one call: its mean, standard
deviation, least, and median.
Properties
check_property(gen, holds, runs) checks that holds is true for runs
random values (100 unless given). When one fails, it is shrunk to the
smallest that still fails, which the failure shows:
func test_sum() do
check_property(gen_items(gen_int(0, 100), 10), func(int[] xs) bool => sum(xs) >= 0)
endValues come from gen_int(low, high), gen_bool(), gen_str(max_length, letters), gen_items(gen, max_length), and gen_one_of(choices, show), or
any Gen[T], which says how to make a value, the smaller values to try,
and how to show one.
Snapshots
assert_snapshot(name, text) keeps text in snapshots/ beside the test
file the first time, and later compares with it; cuarzo test --update-snapshots takes it again when the change is wanted.
Interactive programs
open_terminal(command, columns, rows) starts a program on a terminal of
its own (a pseudo-terminal) and draws what it writes on a screen, as a
terminal would, so a test can drive a full-screen program or a game:
func test_menu() do
TestTerminal t = assert_ok(open_terminal(["build/menu"], 80, 24))
defer t.close()
assert_true(t.wait_for("Choose a file"))
t.send(KEY_DOWN + KEY_ENTER)
assert_true(t.wait_for("Opened"))
assert_true(t.style_at(0, 0).bold)
endsend(keys) types text or keys (KEY_UP, KEY_ENTER, ctrl('c'), and
the others); wait_for(text, timeout_ms) waits for the screen to show
text; text() and line(row) read the screen; style_at(row, column)
gives a character's colors and attributes, as a TerminalStyle of
std/terminal_emulator, which draws the screen; cursor() where the cursor is;
wait_exit(timeout_ms) the program's status. The screen follows the
sequences terminal programs use: cursor movement, erasing, scrolling
regions, the alternate screen, and colors in 16, 256, and 24-bit forms.