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: package-extension:
stage: release stage: release
before_script:
- apk add --no-cache tar
script: script:
- DATE=`date +"%Y-%m-%d"` - 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/,' . - 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 = {}
local tests_by_mod = {}
local TESTS_STATE_ENUM = { local TESTS_STATE_ENUM = {
NOT_STARTED = "not_started", NOT_STARTED = "not_started",
@ -12,14 +13,20 @@ local tests_context = {}
local failed = 0 local failed = 0
test_harness.set_context = function(name, version_string) test_harness.set_context = function(mod, version_string)
tests_context = { table.insert(tests_context, { mod = mod, version_string = version_string})
name = name,
version_string = version_string
}
end 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(type(name) == "string")
assert(func == nil or type(func) == "function") assert(func == nil or type(func) == "function")
if not opts then if not opts then
@ -27,9 +34,19 @@ test_harness.register_test = function(name, func, opts)
else else
opts = test_harness.table_copy(opts) opts = test_harness.table_copy(opts)
end end
opts.mod = mod
opts.name = name opts.name = name
opts.func = func opts.func = func
table.insert(tests, opts) 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 end
@ -317,17 +334,20 @@ local all_in_table = function(names, names_list)
end end
local display_tests_summary = function() local display_tests_summary = function()
for _, test in ipairs(tests) do for mod, tests_list in pairs(tests_by_mod) do
if test.func == nil then print(string.format("%#70s", mod))
local s = "---- " .. test.name .. " " for _, test in ipairs(tests_list) do
print(s .. string.rep("-", 60 - #s)) if test.func == nil then
elseif test.result ~= nil then local s = ":"..test.mod..":---- " .. test.name .. " "
print(string.format("%-60s %s", test.name, test.result.ok and "pass" or "FAIL")) print(s .. string.rep("-", 60 - #s))
if not test.result.ok then elseif test.result ~= nil then
print(" " .. test.result.err) 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 end
else
print(string.format("%-60s %s", test.name, "No result"))
end end
end end
print("Tests done, " .. failed .. " tests failed.") 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 if tests_state == TESTS_STATE_ENUM.DONE then
break break
end 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) local wanted = vec(56, 56, 56)
for x = 0, math.floor(wanted.x / 16) do for x = 0, math.floor(wanted.x / 16) do
for y = 0, math.floor(wanted.y / 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 player_data = save_players(test.players)
local ok, err = pcall(test.func) local ok, err = pcall(test.func)
test.result = { ok = ok, err = err } 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 if not ok then
print(" " .. err) print(" " .. err)
failed = failed + 1 failed = failed + 1
@ -475,8 +500,13 @@ local run_tests = function()
end end
end end
local v = minetest.get_version() 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 end
init_nodes() init_nodes()
@ -495,14 +525,14 @@ local run_tests = function()
area.assign(vec(0, 0, 0), wanted, function() area.assign(vec(0, 0, 0), wanted, function()
for _, test in ipairs(simple_tests) do for _, test in ipairs(simple_tests) do
if not test.func then if not test.func then
local s = "---- " .. test.name .. " " local s = ":"..test.mod..":---- " .. test.name .. " "
print(s .. string.rep("-", 60 - #s)) print(s .. string.rep("-", 60 - #s))
test.result = { ok = true, err = "" } test.result = { ok = true, err = "" }
else else
area.clear() area.clear()
local ok, err = pcall(test.func) local ok, err = pcall(test.func)
test.result = { ok = ok, err = err } 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 if not ok then
print(" " .. err) print(" " .. err)
failed = failed + 1 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 get_node = minetest.get_node
local set_node = minetest.set_node local set_node = minetest.set_node
local air = "air" local air = "air"