Let your QA test itself

Here is a workflow shift worth adopting: the QA is the test. flua gives every QA an exit code — a runtime error exits 1, exit(N) exits N — so a QA can assert its own behavior and report success or failure to whatever runs it. No test framework, no extra files.

--%%name:my_qa_test
local failures = 0

local function assertEq(actual, expected, msg)
  if tostring(actual) == tostring(expected) then
    print("PASS: " .. msg .. " (" .. tostring(actual) .. ")")
  else
    failures = failures + 1
    print("FAIL: " .. msg .. " — expected " .. tostring(expected) .. ", got " .. tostring(actual))
  end
end

function QuickApp:onInit()
  local device = api.get("/devices/" .. self.id)  -- the sim sees the QA
  assertEq(device.id, self.id, "device visible in the sim")

  self:updateProperty("value", 50)
  assertEq(self.properties.value, 50, "updateProperty round trip")

  print("failures:", failures)
  exit(failures > 0 and 1 or 0)
end

Run it (F5 works too — offline is the default, so no flags are needed):

flua --api local my_qa.lua
echo $?          # 0 = everything passed, non-zero = look at the FAIL lines

This is the exact pattern of selfTest.lua in the examples directory (flua --examples). Every change you make can be verified in one command — your own mini test suite, living inside the QA.

Two extensions that make this even more useful:

Next post: when the tests pass — the one-command path from laptop to HC3.

flua: https://github.com/jangabrielsson/flua · agents: USAGE.md + the quickapp-test skill