Test a package
Run a package's tests, choose which run, measure how much of its code they cover, and keep a report of the run.
Where tests live
A package's tests live in its tests/ folder: files named *_test.lua,
helper modules under tests/lib/, and an optional tests/test.kdl of
settings. The folder never ships: packing and running the package leave
it out. A test file loads the package's own modules with require, as
the package's code does:
name "@me/calc"
version "0.1.0"
api_version "*"
kind "library"
license "0BSD"
local numbers = {}
function numbers.clamp(x, low, high)
return math.max(low, math.min(high, x))
end
return numbers
local numbers = require("numbers")
describe("clamp")
it("keeps a value inside the range", function()
expect(numbers.clamp(14, 0, 10)).to_be(10)
expect(numbers.clamp(-3, 0, 10)).to_be(0)
end)
it("leaves a value in range alone", function()
expect(numbers.clamp(4, 0, 10)).to_be(4)
end)
Package testing lists every global a test file
has: describe and it, the expect matchers, and the calls that
wait for frames.
Run the tests
datumhue pkg test runs the suite inside DatumHue, with the package's
real API. Results stream as TAP, and the exit code is the verdict: 0 when
every test passed, 1 when one failed.
$ datumhue pkg test calc
$ datumhue pkg test calc range
$ datumhue pkg test calc --skip alone --seed 1234
$ datumhue pkg test calc --list
- A word after the folder runs only the tests whose full name, such as
clamp > keeps a value inside the range, holds it.--skipleaves out the tests whose name holds its word. A word that matches no test fails the run, so a typo never passes in silence. - Every run prints the seed of its random numbers.
--seedwith that number runs the same rolls again. --listprints the tests' names without running them.- A run stops after 300 seconds;
--timeout, ortimeout-secondsintests/test.kdl, changes that.
A test can also drive the app as a person would: wait for frames, press
keys, move and click the pointer at a widget's UiElement.bounds, and
use a virtual gamepad, through datumhue.debug.input.
Run windowed suites unattended
A suite opens a window, unless its package is a service app. To run it with no display, or out of the way, start it inside a headless compositor such as gamescope. The exit code does not come through gamescope, so read the verdict from the summary the run prints last.
$ gamescope --backend headless -W 390 -H 844 -w 390 -h 844 \
--force-windows-fullscreen -- datumhue pkg test calc
-W and -H size gamescope's output, and -w, -h and
--force-windows-fullscreen size the window your app gets. A test of
your layout at a given size needs both. Run the suite once per size you
support, a phone's portrait and landscape among them.
Measure coverage
datumhue pkg cov runs the same suite and measures which lines and
branches of the package's Lua ran. It prints a table per file
afterward; a module the suite never loaded counts as not covered.
$ datumhue pkg cov calc --fail-under 80
--fail-under fails the run when line coverage is below the
percentage, and --fail-under-branch does the same for branches.
--lcov writes a standard LCOV file for other coverage tools.
Keep a report
Both commands take --report with a file name, and then also write the
run as a web page. The page shows the verdict and every test with what
went wrong in it; for pkg cov it also marks the covered lines of each
source file. --open writes the page and opens it in your browser. The
page is written even when the run fails, and the exit code stays the
same.
$ datumhue pkg cov calc --report coverage.html --open
Debug or profile a suite
datumhue pkg test calc --dap waits for your editor's debugger instead
of running the suite, with breakpoints in your real files, tests
included (Debug an app). --profile records where
the suite's time goes (Find what's slow).
See also
Reference used on this page: UiElement.bounds datumhue.debug.input