Post 6 taught the pattern: a QA can assert its own behavior and exit
with the failure count. Since then flua grew the missing half — a runner.
flua test discovers *_test.lua files, runs each
in its own flua process (with a wall-clock timeout, so a test that never
exits can't block the rest), and reports one PASS/FAIL/TIME line per file.
The assertions come from require("flua-test"), built into
flua — no files to ship, nothing travels in the .fqa:
-- lamp_test.lua
local Test = require("flua-test")
local t = Test.new()
t:expect(true, "the obvious one")
t:assert_eq(2 + 2, 4, "math still works")
local device = api.get("/devices/".._FLUA.qaId)
t:expect(device.id == _FLUA.qaId, "the device is visible in the sim")
t:finish() -- "failures: N" + exit(failures > 0 and 1 or 0)
Make it fail, and the runner tells you why:
-- broken_test.lua
local Test = require("flua-test")
local t = Test.new()
t:assert_eq(2 + 2, 5, "math still works")
t:finish()
.venv/bin/flua test # FAIL broken_test.lua (failures: 1) # PASS lamp_test.lua # flua test: 1 passed, 1 failed, 0 timed out
Exit code 0 only when everything passes — CI-friendly. A test QA that forgets to exit hits the per-file timeout and is reported, not hung:
.venv/bin/flua test --timeout 5 # TIME hanging_test.lua (no exit within 5s — does the test end with t:finish()/exit(...)?)
Explicit file arguments run regardless of their name,
--list shows what would run, -v dumps a failed
test's output. Tests run with the working directory you invoke from, so
.flua-directives overrides and the .env chain
apply exactly as in a normal run — your suite can point a foreign QA's
tests at your credentials without editing anything (post 18).
Next time: when something doesn't work, one command tells you why —
flua doctor.
flua test: USAGE.md · flua-test: src/flua/lua/lib/flua-test.lua · pip: fibaro-flua 0.1.83 · flua: https://github.com/jangabrielsson/flua