🎓 A1Learner
🔍
0 of 49 lessons completed

Lua Test Harnesses

A test harness is a small program that runs a list of checks and reports how many passed. It turns testing into one repeatable run.

A loop runs every test

The tests sit in a table. The loop calls each one and counts the passes.

local tests = {
  function() return 2 + 2 == 4 end,
  function() return "a" .. "b" == "ab" end
}
local passed = 0
for _, test in ipairs(tests) do
  local ok, result = pcall(test)
  if ok and result then passed = passed + 1 end
end
print(passed .. " passed")

One failure does not stop the loop

A failing test is caught. The loop still runs the tests after it.

local tests = {
  function() return true end,
  function() error("boom", 0) end,
  function() return true end
}
local passed = 0
local failed = 0
for _, test in ipairs(tests) do
  local ok, result = pcall(test)
  if ok and result then passed = passed + 1 else failed = failed + 1 end
end
print(passed .. " passed, " .. failed .. " failed")

A false result counts as a failure

A test can fail without an error. Returning false is enough to fail it.

local tests = {
  function() return 5 > 3 end,
  function() return 5 < 3 end,
  function() return 5 == 5 end
}
local passed = 0
for _, test in ipairs(tests) do
  local ok, result = pcall(test)
  if ok and result then passed = passed + 1 end
end
print("passed: " .. passed)

Example

local tests = {
  { name = "add", fn = function() return 3 + 4 == 7 end },
  { name = "upper", fn = function() return string.upper("lua") == "LUA" end },
  { name = "join", fn = function() return table.concat({"a", "b"}, "-") == "a-b" end },
  { name = "divide", fn = function() return 10 / 2 == 6 end }
}
local passed = 0
local failed = {}
for _, test in ipairs(tests) do
  local ok, result = pcall(test.fn)
  if ok and result then passed = passed + 1 else failed[#failed + 1] = test.name end
end
print(passed .. " passed, " .. #failed .. " failed")
print("failed: " .. table.concat(failed, ", "))

Key points

  • Tests: a table holds one function per check.
  • Runner: a loop calls each test function in turn.
  • Guard: pcall catches a failing test without stopping the loop.
  • Pass count: a counter grows by one for each passing test.
  • Report: the harness prints the pass count at the end.

In this example, four named tests run in a loop, each wrapped in pcall. Three return true, so the pass count reaches three. The divide test returns false, so its name lands in the failed list and is printed at the end.

Note

a failing test still counts as a result, not a crash.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

A harness runs 4 tests. Two pass, one fails with an error, and one returns false. What pass count does the harness print?