Changed to use imported TestSuite.lua, instead of embedded in the tests/ folder.
This commit is contained in:
parent
c75ee00f88
commit
4e3d5e2bf9
|
@ -1,254 +0,0 @@
|
|||
|
||||
local TERM_COLOR_CODE_WHITE = '\27[37;1m'
|
||||
local TERM_COLOR_CODE_GREEN = '\27[32;1m'
|
||||
local TERM_COLOR_CODE_RED = '\27[31;1m'
|
||||
local TERM_COLOR_CODE_GREY = '\27[30;0m'
|
||||
|
||||
local ASSERT_ERROR_TYPE = [[
|
||||
Types not compatible:
|
||||
Expected: %s (%s)
|
||||
Gotten: %s (%s)
|
||||
]]
|
||||
|
||||
local ASSERT_ERROR_VALUE = [[
|
||||
Values of type '%s' not equal:
|
||||
Expected: %s
|
||||
Gotten: %s
|
||||
]]
|
||||
|
||||
local ASSERT_ERROR_TABLE_VALUE = [[
|
||||
Values in tables not equal:
|
||||
For key: %s
|
||||
|
||||
Expected: %s (%s)
|
||||
Gotten: %s (%s)
|
||||
]]
|
||||
|
||||
local function assert_equal (expected, gotten)
|
||||
if type(gotten) ~= type(expected) then
|
||||
error(ASSERT_ERROR_TYPE:format(tostring(gotten), type(gotten), tostring(expected), type(expected)))
|
||||
elseif type(expected) == 'table' and gotten ~= expected then
|
||||
for key, expected_value in pairs(expected) do
|
||||
if expected_value ~= gotten[key] then
|
||||
error(ASSERT_ERROR_TABLE_VALUE:format(key, expected_value, type(expected_value), gotten[key], type(gotten[key])))
|
||||
end
|
||||
end
|
||||
elseif gotten ~= expected then
|
||||
error(ASSERT_ERROR_VALUE:format(type(gotten), gotten, expected))
|
||||
end
|
||||
end
|
||||
|
||||
local libraries_tests_and_wrappers = {
|
||||
assert_equal = assert_equal
|
||||
}
|
||||
|
||||
for k, v in pairs(_G) do
|
||||
libraries_tests_and_wrappers[k] = v
|
||||
end
|
||||
|
||||
local function indent_string (str, indent)
|
||||
return indent .. str:gsub('\n', '\n'..indent)
|
||||
end
|
||||
|
||||
local TEST_SUITE_TRACEBACK = "\n\t\t[C]: in function 'xpcall'\n\t\t./TestSuite.lua"
|
||||
|
||||
local function find_cutoff_index_for_traceback_string (str)
|
||||
local index = str:find(TEST_SUITE_TRACEBACK, 1, true)
|
||||
return index
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Lua 5.2 compat
|
||||
|
||||
if not setfenv then -- Lua 5.2
|
||||
-- based on http://lua-users.org/lists/lua-l/2010-06/msg00314.html
|
||||
-- this assumes f is a function
|
||||
local function findenv(f)
|
||||
local level = 1
|
||||
repeat
|
||||
local name, value = debug.getupvalue(f, level)
|
||||
if name == '_ENV' then return level, value end
|
||||
level = level + 1
|
||||
until name == nil
|
||||
return nil end
|
||||
getfenv = function (f) return(select(2, findenv(f)) or _G) end
|
||||
setfenv = function (f, t)
|
||||
local level = findenv(f)
|
||||
if level then debug.setupvalue(f, level, t) end
|
||||
return f end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local TestSuite = {}
|
||||
TestSuite.__index = TestSuite
|
||||
|
||||
function TestSuite.new (module_name)
|
||||
local new_test_suite = setmetatable({}, TestSuite)
|
||||
new_test_suite.name = module_name
|
||||
new_test_suite.submodules = {}
|
||||
new_test_suite.tests = {}
|
||||
new_test_suite.custom_env = {}
|
||||
return new_test_suite
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function TestSuite:setEnviroment (new_enviroment)
|
||||
self.custom_env = new_enviroment
|
||||
end
|
||||
|
||||
function TestSuite:createUniqueEnviroment ()
|
||||
local new_enviroment = {}
|
||||
for k, v in pairs(libraries_tests_and_wrappers) do
|
||||
new_enviroment[k] = v
|
||||
end
|
||||
for k, v in pairs(self.custom_env) do
|
||||
new_enviroment[k] = v
|
||||
end
|
||||
return new_enviroment
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function TestSuite:addModules (modules)
|
||||
for _, module in ipairs(modules) do
|
||||
table.insert(self.submodules, module)
|
||||
end
|
||||
end
|
||||
|
||||
function TestSuite:addTest (test_name, extra_info, test_func)
|
||||
if type(extra_info) == 'function' then
|
||||
extra_info, test_func = test_func, extra_info
|
||||
end
|
||||
|
||||
table.insert(self.tests, {
|
||||
name = test_name,
|
||||
test = test_func,
|
||||
extra_info = extra_info or {}
|
||||
})
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
function TestSuite:runSubmodules (prefix, indent)
|
||||
local total_errors, total_tests = 0, 0
|
||||
for _, module in ipairs(self.submodules) do
|
||||
local errors, tests = module:runTests(prefix, indent)
|
||||
total_errors, total_tests = total_errors + errors, total_tests + tests
|
||||
end
|
||||
return total_errors, total_tests
|
||||
end
|
||||
|
||||
local function setup_debug_hooks (extra_info)
|
||||
assert(not (extra_info.max_time and extra_info.max_lines), "TEST CONFIG ERROR: Only one line hook allowed pr. test!")
|
||||
local trace
|
||||
if extra_info.max_time then
|
||||
local stop_time = os.clock() + extra_info.max_time
|
||||
trace = function (l)
|
||||
if os.clock() >= stop_time then
|
||||
debug.sethook(nil, 'l')
|
||||
error("Test timed out! This is usually symptom of an infinite loop!")
|
||||
end
|
||||
end
|
||||
elseif extra_info.max_lines then
|
||||
local line_countdown = 10 + extra_info.max_lines
|
||||
trace = function (l)
|
||||
line_countdown = line_countdown - 1
|
||||
if line_countdown <= 0 then
|
||||
debug.sethook(nil, 'l')
|
||||
error("Test exteeded allowed number of lines! This is usually symptom of an infinite loop! (Or too low an estimate!)")
|
||||
end
|
||||
end
|
||||
end
|
||||
debug.sethook(trace, 'l')
|
||||
end
|
||||
|
||||
function TestSuite:runTests (parent_prefix, parent_indent)
|
||||
local prefix, indent = self.name, (parent_indent or 0) + 2
|
||||
if parent_prefix then
|
||||
prefix = parent_prefix .. '.' .. prefix
|
||||
else
|
||||
io.write('\n## Running tests ##\n\n')
|
||||
end
|
||||
|
||||
local nr_errors, nr_tests = self:runSubmodules(prefix, indent)
|
||||
|
||||
local function error_handler (err)
|
||||
return err..debug.traceback('', 4)
|
||||
end
|
||||
|
||||
local function print_status (left, right, color)
|
||||
local term_width = 80
|
||||
local color = color or ''
|
||||
io.write(TERM_COLOR_CODE_WHITE..left..': '..string.rep(' ', term_width + 1-#left-#right)..color..right..'\n'..TERM_COLOR_CODE_GREY)
|
||||
end
|
||||
|
||||
for index, test in ipairs(self.tests) do
|
||||
nr_tests = nr_tests + 1
|
||||
-- Setup Test Env, and name
|
||||
local ext_name = prefix .. '.' .. test.name
|
||||
local env = self:createUniqueEnviroment()
|
||||
setfenv(test.test, env)
|
||||
|
||||
setup_debug_hooks(test.extra_info)
|
||||
-- Call tests
|
||||
local success, traceback = xpcall(test.test, error_handler)
|
||||
-- Unset line hook, if set earlier
|
||||
debug.sethook(nil, 'l')
|
||||
-- Write work (or not.)
|
||||
if success then
|
||||
--print_status(ext_name, 'SUCCESS!', TERM_COLOR_CODE_GREEN)
|
||||
else
|
||||
print_status(ext_name, 'ERROR!', TERM_COLOR_CODE_RED)
|
||||
traceback = indent_string(traceback, '\t')
|
||||
local stop_index = find_cutoff_index_for_traceback_string(traceback)
|
||||
io.write('\n'..TERM_COLOR_CODE_GREY)
|
||||
io.write(traceback:sub(1, stop_index))
|
||||
io.write('\n\n')
|
||||
nr_errors = nr_errors + 1
|
||||
end
|
||||
end
|
||||
|
||||
if nr_errors == 0 then
|
||||
print_status(prefix, 'NO ERRORS! WELL DONE!', TERM_COLOR_CODE_GREEN)
|
||||
elseif nr_errors == 1 then
|
||||
print_status(prefix, 'A SINGLE ERROR! ALMOST THERE!', TERM_COLOR_CODE_RED)
|
||||
else
|
||||
print_status(prefix, nr_errors..' ERRORS! GET TO WORK!', TERM_COLOR_CODE_RED)
|
||||
end
|
||||
|
||||
if not parent_prefix then
|
||||
self:writeStatus(nr_errors, nr_tests)
|
||||
end
|
||||
|
||||
return nr_errors, nr_tests
|
||||
end
|
||||
|
||||
function TestSuite:writeStatus ( nr_errors, nr_tests )
|
||||
io.write(TERM_COLOR_CODE_WHITE)
|
||||
io.write('\n## All tests run! ##\n\n')
|
||||
|
||||
local WIDTH_OR_BAR = 70
|
||||
local BAR_CHAR = '#'
|
||||
local nr_successes = nr_tests - nr_errors
|
||||
local size_of_green_bar = math.floor( WIDTH_OR_BAR * nr_successes/nr_tests)
|
||||
|
||||
io.write('Status: ')
|
||||
io.write(nr_errors == 0 and TERM_COLOR_CODE_GREEN or TERM_COLOR_CODE_RED)
|
||||
io.write(BAR_CHAR:rep(WIDTH_OR_BAR))
|
||||
io.write(TERM_COLOR_CODE_WHITE)
|
||||
|
||||
local numbers_str = ' ' .. nr_successes .. ' / ' .. nr_tests .. ' '
|
||||
local half_bar = (WIDTH_OR_BAR-#numbers_str)/2
|
||||
local green_bar = BAR_CHAR:rep(math.floor(half_bar)) .. numbers_str .. BAR_CHAR:rep(math.ceil(half_bar))
|
||||
green_bar = TERM_COLOR_CODE_GREEN .. green_bar:sub(1, size_of_green_bar) .. TERM_COLOR_CODE_RED .. green_bar:sub(size_of_green_bar + 1)
|
||||
|
||||
-- Get
|
||||
io.write('\n\nSummary: '..green_bar..'\n\n')
|
||||
io.write(TERM_COLOR_CODE_WHITE)
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
return TestSuite
|
|
@ -31,7 +31,7 @@ local function format_test (t)
|
|||
local expected_result = t.expect
|
||||
local actual_result = format(input_value, input_options)
|
||||
if not t.approx or type(actual_result) ~= 'string' then
|
||||
assert_equal(actual_result, expected_result)
|
||||
assert_equal(expected_result, actual_result)
|
||||
else
|
||||
if not actual_result:match(expected_result) then
|
||||
error(ASSERT_ERROR_APPROX:format(expected_result, actual_result))
|
||||
|
|
|
@ -1,49 +1,6 @@
|
|||
|
||||
-- Util function
|
||||
|
||||
local function get_test_modules (test_folder_and_prefix)
|
||||
|
||||
local function string_split (str, sep)
|
||||
local t, i = {}, 1
|
||||
for str in string.gmatch(str, "([^".. (sep or '%s') .."]+)") do
|
||||
t[#t+1] = str
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local function os_execute (command)
|
||||
local handle = io.popen(command)
|
||||
local result = handle:read("*a")
|
||||
handle:close()
|
||||
return string_split(result)
|
||||
end
|
||||
|
||||
local function get_test_filenames (dir_and_prefix)
|
||||
return os_execute('ls '..dir_and_prefix)
|
||||
end
|
||||
|
||||
local function load_test_modules (test_filenames)
|
||||
local modules = {}
|
||||
for _, filename in ipairs(test_filenames) do
|
||||
local module = require(filename:sub(1,-5))
|
||||
assert(type(module) == 'table', ('ERROR: Module "%s" did not return a Table value.'):format(filename))
|
||||
modules[#modules+1] = module
|
||||
end
|
||||
return modules
|
||||
end
|
||||
|
||||
local test_filenames = get_test_filenames(test_folder_and_prefix)
|
||||
local test_modules = load_test_modules(test_filenames)
|
||||
return test_modules
|
||||
end
|
||||
|
||||
-- Load modules and run them
|
||||
|
||||
package.path = package.path .. ';./test/?.lua'
|
||||
|
||||
local TEST_SUITE = require("TestSuite").new('Pretty')
|
||||
|
||||
local modules = get_test_modules('test/test_*')
|
||||
TEST_SUITE:addModules(modules)
|
||||
package.path = package.path .. ';./test/?.lua;./src/?.lua'
|
||||
|
||||
local TEST_SUITE = require("TestSuite").new('pretty')
|
||||
TEST_SUITE:addModules('test/test_*')
|
||||
TEST_SUITE:runTests()
|
||||
|
|
Loading…
Reference in New Issue
Block a user