Template repo for tiny cross-platform apps that can be modified on phone, tablet or computer.
at main 66 lines 1.9 kB view raw
1-- Some primitives for tests. 2 3function run_tests() 4 local sorted_names = {} 5 for name,binding in pairs(_G) do 6 if name:find('test_') == 1 then 7 table.insert(sorted_names, name) 8 end 9 end 10 table.sort(sorted_names) 11 Test_errors = {} 12 for _,name in ipairs(sorted_names) do 13 xpcall(_G[name], function(err) prepend_debug_info_to_test_failure(name, err) end) 14 end 15 if #Test_errors > 0 then 16 error(('There were %d test failures:\n%s'):format(#Test_errors, table.concat(Test_errors))) 17 end 18end 19 20function prepend_debug_info_to_test_failure(test_name, err) 21 local err_without_line_number = err:gsub('^[^:]*:[^:]*: ', '') 22 local stack_trace = debug.traceback('', --[[stack frame]]5) -- most likely to be useful, but set to 0 for a complete stack trace 23 local file_and_line_number = stack_trace:gsub('stack traceback:\n', ''):gsub(': .*', '') 24 local full_error = file_and_line_number..':'..test_name..' -- '..err_without_line_number 25 -- uncomment this line for a complete stack trace 26--? local full_error = file_and_line_number..':'..test_name..' -- '..err_without_line_number..'\t\t'..stack_trace:gsub('\n', '\n\t\t') 27 table.insert(Test_errors, full_error) 28end 29 30 31function check(x, msg) 32 if not x then 33 error(msg) 34 end 35end 36 37function check_nil(x, msg) 38 if x ~= nil then 39 error(msg..'; should be nil but got "'..x..'"') 40 end 41end 42 43function check_eq(x, expected, msg) 44 if not eq(x, expected) then 45 error(msg..'; should be "'..expected..'" but got "'..x..'"') 46 end 47end 48 49function eq(a, b) 50 if type(a) ~= type(b) then return false end 51 if type(a) == 'table' then 52 if #a ~= #b then return false end 53 for k, v in pairs(a) do 54 if not eq(b[k], v) then 55 return false 56 end 57 end 58 for k, v in pairs(b) do 59 if not eq(a[k], v) then 60 return false 61 end 62 end 63 return true 64 end 65 return a == b 66end