Module:ScribuntoUnit and Module:ScribuntoUnit/sandbox: Difference between pages
(Difference between pages)
Content deleted Content added
run tests in the order they were defined, not alphabetically |
use require('strict') instead of require('Module:No globals') |
||
Line 101: | Line 101: | ||
function ScribuntoUnit:markTestSkipped() |
function ScribuntoUnit:markTestSkipped() |
||
DebugHelper.raise({ScribuntoUnit = true, skipped = true}, 3) |
DebugHelper.raise({ScribuntoUnit = true, skipped = true}, 3) |
||
end |
|||
------------------------------------------------------------------------------- |
|||
-- Unconditionally fail a test |
|||
-- @param message optional description of the test |
|||
-- |
|||
function ScribuntoUnit:fail(message) |
|||
DebugHelper.raise({ScribuntoUnit = true, text = "Test failed", message = message}, 2) |
|||
end |
end |
||
Line 197: | Line 189: | ||
-- |
-- |
||
function ScribuntoUnit:assertEquals(expected, actual, message) |
function ScribuntoUnit:assertEquals(expected, actual, message) |
||
if type(expected) == 'number' and type(actual) == 'number' then |
if type(expected) == 'number' and type(actual) == 'number' then |
||
self:assertWithinDelta(expected, actual, 1e-8, message) |
self:assertWithinDelta(expected, actual, 1e-8, message) |
||
elseif expected ~= actual then |
elseif expected ~= actual then |
||
DebugHelper.raise({ |
DebugHelper.raise({ |
||
Line 208: | Line 202: | ||
}, 2) |
}, 2) |
||
end |
end |
||
end |
|||
------------------------------------------------------------------------------- |
|||
-- Checks that an input does not have the expected value. |
|||
-- @param message optional description of the test |
|||
-- @example assertNotEquals(5, add(2,2), "2+2 should not be 5") |
|||
-- |
|||
function ScribuntoUnit:assertNotEquals(expected, actual, message) |
|||
if type(expected) == 'number' and type(actual) == 'number' then |
|||
self:assertNotWithinDelta(expected, actual, 1e-8, message) |
|||
elseif expected == actual then |
|||
DebugHelper.raise({ |
|||
ScribuntoUnit = true, |
|||
text = string.format("Failed to assert that %s does not equal expected %s", tostring(actual), tostring(expected)), |
|||
actual = actual, |
|||
expected = expected, |
|||
message = message, |
|||
}, 2) |
|||
end |
|||
end |
end |
||
------------------------------------------------------------------------------- |
------------------------------------------------------------------------------- |
||
-- Checks that 'actual' is within 'delta' of 'expected'. |
|||
-- Validates that both the expected and actual values are numbers |
|||
-- @param message optional description of the test |
-- @param message optional description of the test |
||
-- @example assertEquals(1/3, 9/3, "9/3 should be 1/3", 0.000001) |
|||
-- |
|||
function ScribuntoUnit:assertWithinDelta(expected, actual, delta, message) |
|||
if type(expected) ~= "number" then |
if type(expected) ~= "number" then |
||
DebugHelper.raise({ |
DebugHelper.raise({ |
||
Line 241: | Line 217: | ||
expected = expected, |
expected = expected, |
||
message = message, |
message = message, |
||
}, |
}, 2) |
||
end |
end |
||
if type(actual) ~= "number" then |
if type(actual) ~= "number" then |
||
Line 250: | Line 226: | ||
expected = expected, |
expected = expected, |
||
message = message, |
message = message, |
||
}, |
}, 2) |
||
end |
end |
||
end |
|||
------------------------------------------------------------------------------- |
|||
-- Checks that 'actual' is within 'delta' of 'expected'. |
|||
-- @param message optional description of the test |
|||
-- @example assertWithinDelta(1/3, 3/9, 0.000001, "3/9 should be 1/3") |
|||
function ScribuntoUnit:assertWithinDelta(expected, actual, delta, message) |
|||
validateNumbers(expected, actual, message) |
|||
local diff = expected - actual |
local diff = expected - actual |
||
if diff < 0 then diff = - diff end -- instead of importing math.abs |
if diff < 0 then diff = - diff end -- instead of importing math.abs |
||
Line 266: | Line 234: | ||
ScribuntoUnit = true, |
ScribuntoUnit = true, |
||
text = string.format("Failed to assert that %f is within %f of expected %f", actual, delta, expected), |
text = string.format("Failed to assert that %f is within %f of expected %f", actual, delta, expected), |
||
actual = actual, |
|||
expected = expected, |
|||
message = message, |
|||
}, 2) |
|||
end |
|||
end |
|||
------------------------------------------------------------------------------- |
|||
-- Checks that 'actual' is not within 'delta' of 'expected'. |
|||
-- @param message optional description of the test |
|||
-- @example assertNotWithinDelta(1/3, 2/3, 0.000001, "1/3 should not be 2/3") |
|||
function ScribuntoUnit:assertNotWithinDelta(expected, actual, delta, message) |
|||
validateNumbers(expected, actual, message) |
|||
local diff = expected - actual |
|||
if diff < 0 then diff = - diff end -- instead of importing math.abs |
|||
if diff <= delta then |
|||
DebugHelper.raise({ |
|||
ScribuntoUnit = true, |
|||
text = string.format("Failed to assert that %f is not within %f of expected %f", actual, delta, expected), |
|||
actual = actual, |
actual = actual, |
||
expected = expected, |
expected = expected, |
||
Line 424: | Line 373: | ||
}, 2) |
}, 2) |
||
end |
end |
||
end |
|||
------------------------------------------------------------------------------- |
|||
-- Checks whether a function doesn't throw an error |
|||
-- @param fn the function to test |
|||
-- @param message optional description of the test |
|||
function ScribuntoUnit:assertDoesNotThrow(fn, message) |
|||
local succeeded, actualMessage = pcall(fn) |
|||
if succeeded then |
|||
return |
|||
end |
|||
-- For strings, strip the line number added to the error message |
|||
actualMessage = type(actualMessage) == 'string' |
|||
and string.match(actualMessage, 'Module:[^:]*:[0-9]*: (.*)') |
|||
or actualMessage |
|||
DebugHelper.raise({ |
|||
ScribuntoUnit = true, |
|||
actual = actualMessage, |
|||
text = string.format('Expected no exception, but got exception with message %s', |
|||
tostring(actualMessage) |
|||
), |
|||
message = message |
|||
}, 2) |
|||
end |
end |
||
Line 455: | Line 381: | ||
function ScribuntoUnit:new(o) |
function ScribuntoUnit:new(o) |
||
o = o or {} |
o = o or {} |
||
o |
setmetatable(o, {__index = self}) |
||
setmetatable(o, { |
|||
__index = self, |
|||
__newindex = function (t, k, v) |
|||
if type(k) == "string" and k:find('^test') and type(v) == "function" then |
|||
-- Store test functions in the order they were defined |
|||
table.insert(o._tests, {name = k, test = v}) |
|||
else |
|||
rawset(t, k, v) |
|||
end |
|||
end |
|||
}) |
|||
o.run = function(frame) return self:run(o, frame) end |
o.run = function(frame) return self:run(o, frame) end |
||
return o |
return o |
||
Line 501: | Line 416: | ||
else |
else |
||
self.failureCount = self.failureCount + 1 |
self.failureCount = self.failureCount + 1 |
||
local message = details.source |
local message = details.source |
||
if details.message then |
if details.message then |
||
message = message .. details.message .. "\n" |
message = message .. details.message .. "\n" |
||
Line 515: | Line 430: | ||
function ScribuntoUnit:runSuite(suite, frame) |
function ScribuntoUnit:runSuite(suite, frame) |
||
self:init(frame) |
self:init(frame) |
||
local names = {} |
|||
for i, testDetails in ipairs(suite._tests) do |
|||
for name in pairs(suite) do |
|||
self:runTest(suite, testDetails.name, testDetails.test) |
|||
if name:find('^test') then |
|||
table.insert(names, name) |
|||
end |
|||
end |
|||
table.sort(names) -- Put tests in alphabetical order. |
|||
for i, name in ipairs(names) do |
|||
local func = suite[name] |
|||
self:runTest(suite, name, func) |
|||
end |
end |
||
return { |
return { |
||
Line 603: | Line 526: | ||
name = name .. ' / ' .. result.testname |
name = name .. ' / ' .. result.testname |
||
end |
end |
||
text = text .. |
text = text .. name .. '\n| ' .. mw.text.nowiki(tostring(result.expected)) .. '\n| ' .. mw.text.nowiki(tostring(result.actual)) .. '\n' |
||
else |
else |
||
text = text .. |
text = text .. result.name .. '\n| ' .. ' colspan="2" | ' .. mw.text.nowiki(result.message) .. '\n' |
||
end |
end |
||
else |
else |
||
text = text .. '| ' .. successIcon .. '\n| ' .. |
text = text .. '| ' .. successIcon .. '\n| ' .. result.name .. '\n|\n|\n' |
||
end |
end |
||
end |
end |