Suites and Actions¶
A suite groups related tests; an action is a single test. Wisp has no other concept — there are no nested suites, no hooks, and no tags.
Creating a suite¶
Wisp.suite(name) takes a non-empty name and immediately registers the suite with the
default runner, so it will be picked up by the next Wisp() call.
Suites are flat. If you want grouping in the output, put it in the name:
Adding actions¶
| Parameter | Type | Description |
|---|---|---|
name |
string |
Printed in the report. Make it describe the behaviour, not the mechanics. |
func |
() -> () |
The test body. Called with no arguments. |
Suite:action returns the suite, not the action. That is what makes the chain work:
Wisp.suite("Calculator")
:action("first", function() end)
:action("second", function() end)
:action("third", function() end)
Execution order¶
Actions run in the order they were added, and suites run in the order they were registered:
Wisp.suite("First"):action("a", function() end):action("b", function() end)
Wisp.suite("Second"):action("a", function() end)
Wisp()
-- First → a, b
-- Second → a
Registration happens at the moment Wisp.suite(name) is called, not when the run
starts. So the order suites appear in the report is the order those lines executed during
the require phase.
Failures do not stop the run¶
Every action is invoked through pcall. If it raises — because an assertion failed, or
because your own code threw — the error message is recorded and the next action runs:
Wisp.suite("Robust")
:action("explodes", function()
error("kaboom")
end)
:action("still runs", function()
Wisp.assume(true):isTrue()
end)
Robust
✗ explodes
./run.luau:4: kaboom
✓ still runs
Suites: 0 passed out of 1 total
Tests: 1 passed out of 2 total
This is the main behavioural difference from a plain script of error calls: one broken
test does not hide the rest of the report.
Only the action's own error is caught
If the reporter raises — for example Runner:pass is called for a suite that was
never registered — that error is not caught and will propagate out of Wisp().
Unique names¶
A runner keys its statistics by suite name. Registering a second suite with a name that is already taken is silently ignored, and that suite's actions will never run:
Wisp.suite("Duplicated")
:action("this runs", function() end)
Wisp.suite("Duplicated")
:action("this never runs", function()
error("should not get here")
end)
If a suite is missing from your report, look for a name collision before anything else.
The suite object¶
Wisp.suite returns a live Suite instance. It is rarely useful, but it is public API —
see Suite for the full reference, including how to construct one
against your own runner.
Next¶
- Assertions — the expectations you write inside an action.
- Reading the report — what the output means.