A simple single-file unit test system for Lua with a somewhat rich set of assertions and custom error messages. Features:
- Lua 5.2,5.3 compatible.
- Framework is a single file.
- Control the order that tests are run (by renaming functions).
- Can output ANSI (for conforming terminals) or HTML (for TextMate or e).
- Sensible (to me) injection of functions while preserving global scope.
- Rich set of assertions and custom error messages.
(Including assertion for comparing tables of values.)
-- This magic line makes a `test` table available,
-- and makes all the assertions available to your tests
_ENV = require('lunity')()
-- Define tests that you want to run inside the `test` table
function test.simplest_assertion()
assert(true, "If true isn't true, we are in big trouble.")
end
-- At the end of your file, call `test()` to run the tests
test()
-- You can optionally give a name to your test suite
_ENV = require('lunity')('check robustness')
function test:before()
-- code here will be run before each test
-- `self` is available to store information needed for the test
end
function test:after()
-- run after each test, in case teardown is needed
end
-- Tests can have any name (other than 'before' or 'after')
-- The `self` table is the same scratchpad available to before()
function test:foo()
assertTrue(42 == 40 + 2)
assertFalse(42 == 40)
assertEqual(42, 40 + 2)
assertNotEqual(42, 40, "These better not be the same!")
assertTableEquals({ a=42 }, { ["a"]=6*7 })
-- See below for more assertions available
end
-- You can define helper functions for your tests to call with impunity
local function some_utility()
return "excellent"
end
-- Tests will be run in alphabetical order of the entire function name
-- However, relying on the order of tests is an anti-pattern; don't do it
function test:bar()
assertType(some_utility(), "string")
end
local allPassed = test{
useANSI=false, -- turn off ANSI codes (colors/bold) in the output
useHTML=true, -- turn on HTML markup in the output
quiet=true, -- silence print() and io.write() other than Lua during the tests
}
if not allPassed then os.exit(1) end
The msg
parameter is always optional; effort has been made to provide a helpful message if none is provided.
fail(msg)
- instantly fail the testassert(testCondition, msg)
- fail iftestCondition
is eithernil
orfalse
assertEqual(actual, expected, msg)
- fail ifactual ~= expected
assertNotEqual(actual, expected, msg)
- fail ifactual == expected
assertTableEquals(actual, expected, msg)
- recursively compare two tables and fail if they have any different keys or valuesassertTrue(actual, msg)
- fail ifactual ~= true
assertFalse(actual, msg)
- fail ifactual ~= false
assertNil(actual, msg)
- fail ifactual ~= nil
assertNotNil(actual, msg)
- fail ifactual == nil
assertType(actual, expectedType, msg)
- fail iftype(actual) ~= expectedType
, e.g.assertType(getResults(),"table","getResults() needs to return a table")
assertTableEmpty(actual, msg)
- fail ifactual
is not a table, or ifactual
is a table with any keys (including a key with the value offalse
)assertTableNotEmpty(actual, msg)
- fail ifactual
is not a table, or ifactual
does not have any keysassertSameKeys(table1, table2, msg)
- fail if either table has a key not present in the other (good for set comparisons)assertInvokable(value, msg)
- fail ifactual
is not a function, or may not be invoked as one (viameta.__call
)assertErrors(invokable, ...)
- call the functioninvokable
passing along extra parameters, and fail if no errors are raisedassertDoesNotError(invokable, ...)
- call the functioninvokable
passing along extra parameters, and fail if any errors are raised
The following functions are made available to your tests, though they do not count as assertions and will not cause a test failure on their own.
is_nil(value)
- return true ifvalue
isnil
is_boolean(value)
- return true ifvalue
is a booleanis_number(value)
- return true ifvalue
is a numberis_string(value)
- return true ifvalue
is a stringis_table(value)
- return true ifvalue
is a tableis_function(value)
- return true ifvalue
is a functionis_thread(value)
- return true ifvalue
is a threadis_userdata(value)
- return true ifvalue
is a userdata value
Note that while writing assert(is_table(value))
looks nicer in code than assertType(value, 'table')
, the latter provides a better default error message to the user.
This work is licensed under the Creative Commons Attribution 3.0 United States License. To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/ or send a letter to
Creative Commons
171 Second Street, Suite 300
San Francisco, California, 94105, USA
Modification, reuse and redistribution permitted provided the following attribution and copyright line is included:
Copyright (c) 2012-2020 by Gavin Kistner (Phrogz)