Testing
Testing
Section titled “Testing”Write and run tests for your Lua code with the wippy/test framework — a BDD-style
runner with assertions, lifecycle hooks, and mocking, executed by the wippy run test
command.
What You’ll Build
Section titled “What You’ll Build”A small library and a test suite that covers it:
- A
calclibrary withaddanddivfunctions. - A test entry that describes cases, asserts behavior, and skips a pending case.
- A green test run via
wippy run test.
Prerequisites
Section titled “Prerequisites”-
A Wippy project (clone app-template, or
wippy initin an empty directory). -
The test framework and a terminal host installed:
Terminal window wippy add wippy/testwippy add wippy/terminalwippy installThe runner renders a live terminal UI, so
wippy/terminalis required alongsidewippy/test.
The Code Under Test
Section titled “The Code Under Test”-- src/calc.lualocal function add(a, b) return a + bend
local function div(a, b) if b == 0 then return nil, "division by zero" end return a / bend
return { add = add, div = div }The Test
Section titled “The Test”A test is an ordinary function.lua entry tagged with meta.type: test. Its method
returns the value produced by test.run_cases(...), which the runner invokes:
-- src/calc_test.lualocal test = require("test")local calc = require("calc")
local function define_tests() test.describe("calculator", function() local started = false
test.before_all(function() started = true end)
test.it("setup ran", function() test.is_true(started) end)
test.it("adds numbers", function() test.eq(calc.add(2, 3), 5) end)
test.it("returns error on divide by zero", function() local result, err = calc.div(1, 0) test.has_error(result, err) test.contains(err, "division by zero") end)
test.it_skip("not implemented yet", function() test.fail("should not run") end) end)end
return { run = test.run_cases(define_tests) }Register both entries. Discovery keys off meta.type: test; meta.suite groups the
results in the output:
version: "1.0"namespace: app
entries: - name: calc kind: library.lua source: file://calc.lua
- name: calc_test kind: function.lua meta: name: Calculator Test type: test suite: calculator source: file://calc_test.lua method: run imports: test: wippy.test:test calc: app:calcThe imports map controls what require(...) resolves to inside the test: test
binds the framework, calc binds the unit under test.
Run It
Section titled “Run It”wippy run testFilter by entry id substring (namespace:name) while iterating:
wippy run test calc_testOutput for the suite above:
calculator (4) 3/4 1 skipped 1ms o setup ran o adds numbers o returns error on divide by zero - not implemented yet (skipped)
PASSED 3 tests 1 skipped 1mswippy run test exits 0 when every case passes and 1 on any failure, so it drops
straight into CI.
Assertions
Section titled “Assertions”Each assertion raises on failure; the type guards also return the validated value.
| Assertion | Checks |
|---|---|
test.eq(a, b) / test.neq(a, b) | Equality / inequality |
test.ok(v) / test.fail(msg) | Truthy / force a failure |
test.is_nil(v) / test.not_nil(v) | Nil / non-nil |
test.is_true(v) / test.is_false(v) | Boolean value |
test.is_string/number/table/function/boolean(v) | Type guards (return v) |
test.contains(str, sub) / test.matches(str, pattern) | Substring / Lua pattern |
test.has_key(tbl, key) / test.len(v, n) | Map key / length |
test.gt/gte/lt/lte(a, b) | Numeric comparison |
test.throws(fn) / test.has_error(val, err) / test.no_error(val, err) | Error handling |
All take an optional trailing message argument.
Lifecycle and Mocking
Section titled “Lifecycle and Mocking”Call these inside a describe block:
test.before_all/test.after_all— run once per block.test.before_each/test.after_each— run around every case.test.mock("module.field", fn)— replace a function for the current case; mocks restore automatically after each case. Usetest.restore_all_mocks()to clear them early.
Nested describe blocks inherit parent hooks (outer before_* first, inner
after_* first).
Next Steps
Section titled “Next Steps”- Hello World — the minimal project layout
- Entry Kinds —
function.lua,library.lua, and friends - Test Framework — full reference for the runner and event protocol