mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 22:34:56 +00:00
178 lines
5.1 KiB
Lua
178 lines
5.1 KiB
Lua
-- Suite runner
|
|
-- Executes test suites with nested suite support
|
|
|
|
local STATUS = require("test_status")
|
|
local run_test = require("run_test")
|
|
|
|
---@class SuiteRunnerModule
|
|
local M = {}
|
|
|
|
---@class SuiteStats
|
|
---@field total number Total test count
|
|
---@field passed number Passed test count
|
|
---@field failed number Failed test count
|
|
---@field skipped number Skipped test count
|
|
---@field duration number Suite duration in ms
|
|
|
|
---@class SuiteResults
|
|
---@field name string Suite name
|
|
---@field tests TestResult[] Test results
|
|
---@field nested SuiteResults[] Nested suite results
|
|
---@field stats SuiteStats Statistics
|
|
|
|
---Run a test suite
|
|
---@param suite TestSuite Suite to run
|
|
---@param config? TestConfig Run configuration
|
|
---@param parentHooks? TestHooks Parent suite hooks
|
|
---@return SuiteResults Suite execution results
|
|
function M.runSuite(suite, config, parentHooks)
|
|
local results = {
|
|
name = suite.name,
|
|
tests = {},
|
|
nested = {},
|
|
stats = {
|
|
total = 0,
|
|
passed = 0,
|
|
failed = 0,
|
|
skipped = 0,
|
|
duration = 0
|
|
}
|
|
}
|
|
|
|
config = config or {}
|
|
parentHooks = parentHooks or {}
|
|
|
|
local startTime = os.clock()
|
|
|
|
-- Combine hooks with parent hooks
|
|
local hooks = {
|
|
beforeEach = suite.beforeEach or parentHooks.beforeEach,
|
|
afterEach = suite.afterEach or parentHooks.afterEach
|
|
}
|
|
|
|
-- Run beforeAll hook
|
|
if suite.beforeAll then
|
|
local success, err = pcall(suite.beforeAll)
|
|
if not success then
|
|
for _, test in ipairs(suite.tests) do
|
|
results.tests[#results.tests + 1] = {
|
|
name = test.name,
|
|
status = STATUS.FAILED,
|
|
error = "beforeAll failed: " .. tostring(err),
|
|
duration = 0
|
|
}
|
|
results.stats.failed = results.stats.failed + 1
|
|
results.stats.total = results.stats.total + 1
|
|
end
|
|
results.stats.duration = (os.clock() - startTime) * 1000
|
|
return results
|
|
end
|
|
end
|
|
|
|
-- Check for .only tests
|
|
local hasOnly = false
|
|
for _, test in ipairs(suite.tests) do
|
|
if test.only then
|
|
hasOnly = true
|
|
break
|
|
end
|
|
end
|
|
|
|
-- Run tests
|
|
for _, test in ipairs(suite.tests) do
|
|
if hasOnly and not test.only then
|
|
local skipResult = {
|
|
name = test.name,
|
|
status = STATUS.SKIPPED,
|
|
duration = 0
|
|
}
|
|
results.tests[#results.tests + 1] = skipResult
|
|
results.stats.skipped = results.stats.skipped + 1
|
|
elseif config.filter and not string.find(test.name, config.filter, 1, true) then
|
|
local skipResult = {
|
|
name = test.name,
|
|
status = STATUS.SKIPPED,
|
|
duration = 0
|
|
}
|
|
results.tests[#results.tests + 1] = skipResult
|
|
results.stats.skipped = results.stats.skipped + 1
|
|
else
|
|
local testResult = run_test.runTest(test, hooks)
|
|
results.tests[#results.tests + 1] = testResult
|
|
|
|
if testResult.status == STATUS.PASSED then
|
|
results.stats.passed = results.stats.passed + 1
|
|
elseif testResult.status == STATUS.FAILED then
|
|
results.stats.failed = results.stats.failed + 1
|
|
if config.stopOnFirstFailure then
|
|
break
|
|
end
|
|
elseif testResult.status == STATUS.SKIPPED then
|
|
results.stats.skipped = results.stats.skipped + 1
|
|
end
|
|
end
|
|
|
|
results.stats.total = results.stats.total + 1
|
|
end
|
|
|
|
-- Run nested suites
|
|
for _, nestedSuite in ipairs(suite.nested) do
|
|
local nestedResults = M.runSuite(nestedSuite, config, hooks)
|
|
results.nested[#results.nested + 1] = nestedResults
|
|
|
|
-- Aggregate stats
|
|
results.stats.total = results.stats.total + nestedResults.stats.total
|
|
results.stats.passed = results.stats.passed + nestedResults.stats.passed
|
|
results.stats.failed = results.stats.failed + nestedResults.stats.failed
|
|
results.stats.skipped = results.stats.skipped + nestedResults.stats.skipped
|
|
end
|
|
|
|
-- Run afterAll hook
|
|
if suite.afterAll then
|
|
pcall(suite.afterAll)
|
|
end
|
|
|
|
results.stats.duration = (os.clock() - startTime) * 1000
|
|
|
|
return results
|
|
end
|
|
|
|
---Run all suites
|
|
---@param suites TestSuite[] Array of suites to run
|
|
---@param config? TestConfig Run configuration
|
|
---@return table All results with aggregated stats
|
|
function M.runAll(suites, config)
|
|
local allResults = {
|
|
suites = {},
|
|
stats = {
|
|
total = 0,
|
|
passed = 0,
|
|
failed = 0,
|
|
skipped = 0,
|
|
duration = 0,
|
|
suiteCount = 0
|
|
},
|
|
timestamp = os.date("%Y-%m-%dT%H:%M:%S")
|
|
}
|
|
|
|
local startTime = os.clock()
|
|
|
|
for _, suite in ipairs(suites) do
|
|
local suiteResults = M.runSuite(suite, config)
|
|
allResults.suites[#allResults.suites + 1] = suiteResults
|
|
allResults.stats.suiteCount = allResults.stats.suiteCount + 1
|
|
|
|
allResults.stats.total = allResults.stats.total + suiteResults.stats.total
|
|
allResults.stats.passed = allResults.stats.passed + suiteResults.stats.passed
|
|
allResults.stats.failed = allResults.stats.failed + suiteResults.stats.failed
|
|
allResults.stats.skipped = allResults.stats.skipped + suiteResults.stats.skipped
|
|
end
|
|
|
|
allResults.stats.duration = (os.clock() - startTime) * 1000
|
|
allResults.stats.success = allResults.stats.failed == 0
|
|
|
|
return allResults
|
|
end
|
|
|
|
return M
|