Introduction¶
Wisp is a test framework for Luau, the scripting language used by Roblox. You group tests into named suites, you assert things inside those tests, and you get a small printed summary at the end.
local Wisp = require("wisp")
Wisp.suite("Cart")
:action("starts empty", function()
Wisp.assume(#cart.items):equalsTo(0)
end)
Wisp()
The mental model¶
There are only three moving parts.
1. The module. You require Wisp once. The returned value is both a table and a
function, so it can be both configured and invoked:
2. Suites and actions. A suite is a named bucket of actions; an action is a single
named test. Suite:action returns the suite, so calls chain:
3. Assertions. Wisp.assume(value) wraps a value and hands back an Assertion
whose methods describe what you expect. An assertion fails by raising a Lua error,
which Wisp catches and reports as a failed test.
Wisp.assume(2 + 2):equalsTo(4)
Wisp.assume(name):isType("string")
Wisp.assume(compute()):notThrows()
Design goals¶
| Goal | How Wisp meets it |
|---|---|
| Readable output | The report is printed as plain text — no colours, no JSON, no reporter plugin. |
| Cheap to run | A few hundred lines, no dependency tree. Startup cost is a single require. |
| Hard to misuse | Every method is either satisfied or raises. Nothing returns a boolean you might forget to check. |
| Typed | The source is --!strict and exports its types for your editor or LSP. |
What Wisp does not do¶
Being small is a feature, but it also means some things are absent. Knowing the edges up front will save you time.
- No async / hooks. There is no
beforeEach,afterEach,before,after, or promise support. Each action is a plain() -> ()and is expected to finish on its own. - No
.only/.skip. Every registered suite and action always runs. - No exit code control. A failing run still exits
0. See Reading the report if you need a non-zero status. - No custom reporters. The report format is fixed; see Runner if you want to drive suites yourself.
- One default runner. All of
Wisp.suiteandWisp()share a single process-wide runner. Suite names must therefore be unique.
Requirements¶
- Luau (or Lune) that supports string interpolation with backticks and
utf8.char. Wisp's own source relies on these, and your test files will naturally use them too. - Strict mode is supported but not required. Wisp ships
--!strictsource and atypes.d.luaumodule so tooling can inferSuiteandAssertionfor you.
Next¶
Install it with Installation, then write a test in Your First Test.