feat(tests): introduce modular test registration

- Adds support for registering tests under specific modules to enhance organization and categorization.
- Introduces `register_test` function scoped within a module using `get_test_registrator`.
- Track tests by module for improved visibility and management.
- Enhances test output formatting to include module information alongside test names.
This commit is contained in:
Yves-Marie Haussonne 2024-10-02 01:42:45 +02:00
parent 6514938564
commit b40bbafd4c
3 changed files with 55 additions and 23 deletions

View File

@ -79,6 +79,8 @@ release-image_client:
package-extension:
stage: release
before_script:
- apk add --no-cache tar
script:
- DATE=`date +"%Y-%m-%d"`
- tar zcf test_harness_${DATE}_${CI_COMMIT_REF_SLUG}.tar.gz --exclude .luacheckrc --exclude .gitlab-ci.yml --exclude .vscode --exclude .util --exclude client --exclude opengl --exclude \*.tar.gz --exclude .git\* --warning=no-file-changed --transform 's,^./,test_harness/,' .

View File

@ -1,4 +1,5 @@
local tests = {}
local tests_by_mod = {}
local TESTS_STATE_ENUM = {
NOT_STARTED = "not_started",
@ -12,14 +13,20 @@ local tests_context = {}
local failed = 0
test_harness.set_context = function(name, version_string)
tests_context = {
name = name,
version_string = version_string
}
test_harness.set_context = function(mod, version_string)
table.insert(tests_context, { mod = mod, version_string = version_string})
end
test_harness.register_test = function(name, func, opts)
local register_test = function(mod, name, func, opts)
local modnames = minetest.get_modnames()
local is_mod = false
for i=1,#modnames do
if modnames[i]==mod then
is_mod=true
break
end
end
assert(is_mod)
assert(type(name) == "string")
assert(func == nil or type(func) == "function")
if not opts then
@ -27,9 +34,19 @@ test_harness.register_test = function(name, func, opts)
else
opts = test_harness.table_copy(opts)
end
opts.mod = mod
opts.name = name
opts.func = func
table.insert(tests, opts)
local mod_test_list = tests_by_mod[mod] or {}
tests_by_mod[mod] = mod_test_list
table.insert(mod_test_list, opts)
end
test_harness.get_test_registrator = function(mod)
return function(name, func, opts)
register_test(mod, name, func, opts)
end
end
@ -317,17 +334,20 @@ local all_in_table = function(names, names_list)
end
local display_tests_summary = function()
for _, test in ipairs(tests) do
if test.func == nil then
local s = "---- " .. test.name .. " "
print(s .. string.rep("-", 60 - #s))
elseif test.result ~= nil then
print(string.format("%-60s %s", test.name, test.result.ok and "pass" or "FAIL"))
if not test.result.ok then
print(" " .. test.result.err)
for mod, tests_list in pairs(tests_by_mod) do
print(string.format("%#70s", mod))
for _, test in ipairs(tests_list) do
if test.func == nil then
local s = ":"..test.mod..":---- " .. test.name .. " "
print(s .. string.rep("-", 60 - #s))
elseif test.result ~= nil then
print(string.format(":%s:%-60s %s", test.mod,test.name, test.result.ok and "pass" or "FAIL"))
if not test.result.ok then
print(" " .. test.result.err)
end
else
print(string.format(":%s:%-60s %s", test.mod, test.name, "No result"))
end
else
print(string.format("%-60s %s", test.name, "No result"))
end
end
print("Tests done, " .. failed .. " tests failed.")
@ -412,7 +432,12 @@ local run_player_tests = function(list_player_tests)
if tests_state == TESTS_STATE_ENUM.DONE then
break
end
if not test.result and test.func and test.players and next(test.players) and all_in_table(test.players, connected_player_names) then
if not test.result and
test.func and
test.players and
next(test.players) and
all_in_table(test.players, connected_player_names)
then
local wanted = vec(56, 56, 56)
for x = 0, math.floor(wanted.x / 16) do
for y = 0, math.floor(wanted.y / 16) do
@ -426,7 +451,7 @@ local run_player_tests = function(list_player_tests)
local player_data = save_players(test.players)
local ok, err = pcall(test.func)
test.result = { ok = ok, err = err }
print(string.format("%-60s %s", test.name, ok and "pass" or "FAIL"))
print(string.format(":%s:%-60s %s", test.mod, test.name, ok and "pass" or "FAIL"))
if not ok then
print(" " .. err)
failed = failed + 1
@ -475,8 +500,13 @@ local run_tests = function()
end
end
local v = minetest.get_version()
print("Running " .. nb_tests .. " tests for " .. (tests_context.name or "") .. " " ..
(tests_context.version_string or "") .. " on " .. v.project .. " " .. (v.hash or v.string))
print("Running " .. nb_tests .. " tests for:")
for _,context in ipairs(tests_context) do
print(" - "..context.mod .." - "..context.version_string)
end
print("on " .. v.project .. " " .. (v.hash or v.string))
end
init_nodes()
@ -495,14 +525,14 @@ local run_tests = function()
area.assign(vec(0, 0, 0), wanted, function()
for _, test in ipairs(simple_tests) do
if not test.func then
local s = "---- " .. test.name .. " "
local s = ":"..test.mod..":---- " .. test.name .. " "
print(s .. string.rep("-", 60 - #s))
test.result = { ok = true, err = "" }
else
area.clear()
local ok, err = pcall(test.func)
test.result = { ok = ok, err = err }
print(string.format("%-60s %s", test.name, ok and "pass" or "FAIL"))
print(string.format(":%s:%-60s %s", test.mod, test.name, ok and "pass" or "FAIL"))
if not ok then
print(" " .. err)
failed = failed + 1

View File

@ -1,4 +1,4 @@
local register_test = test_harness.register_test
local register_test = test_harness.get_test_registrator("test_harness")
local get_node = minetest.get_node
local set_node = minetest.set_node
local air = "air"