Difference between revisions of "Module:Math/testcases"

From blackwiki
Jump to navigation Jump to search
blackwiki>Mr. Stradivarius
(test using Module:ScribuntoUnit for test cases)
m (25 revisions imported)
 
(22 intermediate revisions by 2 users not shown)
Line 1: Line 1:
-- Unit tests for [[Module:Math]]. Click talk page to run tests.
+
-- Unit tests for [[Module:Math/sandbox]]. Click talk page to run tests.
  
local mm = require('Module:Math/sandbox') -- the module to be tested
+
local moduleName = 'Math/sandbox' -- assigning this to a variable as it is later used to generate an #invoke statement.
 +
local mm = require('Module:' .. moduleName)
 
local ScribuntoUnit = require('Module:ScribuntoUnit')
 
local ScribuntoUnit = require('Module:ScribuntoUnit')
 
local suite = ScribuntoUnit:new()
 
local suite = ScribuntoUnit:new()
  
local function invokeMath(funcName, argString)
+
-------------------------------------------------------------------------------
return '{{#invoke:math/sandbox|' .. funcName .. argString or '' .. '}}'
+
-- Helper functions
 +
-------------------------------------------------------------------------------
 +
 
 +
function suite.getLuaResult(funcName, args)
 +
args = args or {}
 +
local result = mm['_' .. funcName](unpack(args))
 +
return result
 +
end
 +
 
 +
function suite:assertLuaEquals(expected, funcName, args)
 +
args = args or {}
 +
self:assertEquals(expected, self.getLuaResult(funcName, args))
 +
end
 +
 
 +
function suite.buildInvocation(funcName, args)
 +
args = args or {}
 +
local argsClone = mw.clone(args)
 +
-- Build a module invocation equivalent to the args table. Taken from [[Module:Unsubst]].
 +
-- Numbered args first.
 +
local ret = '{{#invoke:' .. moduleName .. '|' .. funcName
 +
for k, v in ipairs(argsClone) do
 +
v = tostring(v)
 +
if string.find(v, '=', 1, true) then
 +
-- likely something like 1=foo=bar, we need to do it as a named arg
 +
break
 +
end
 +
ret = ret .. '|' .. v
 +
argsClone[k] = nil
 +
end
 +
for k, v in pairs(argsClone) do
 +
k = tostring(k)
 +
v = tostring(v)
 +
ret = ret .. '|' .. k .. '=' .. v
 +
end
 +
return ret .. '}}'
 +
end
 +
 
 +
function suite:getInvokeResult(funcName, args, convertNumber) -- Unless convertNumber is false, the number is converted to a number, if possible, on re-entry to Lua.
 +
args = args or {}
 +
local invocation = self.buildInvocation(funcName, args)
 +
local result = self.frame:preprocess(invocation)
 +
if convertNumber ~= false and tonumber(result) then
 +
return tonumber(result)
 +
else
 +
return result
 +
end
 
end
 
end
+
 
--[[
+
function suite:assertInvokeEquals(expected, funcName, args, convertNumber)
 +
args = args or {}
 +
local invokeResult = self:getInvokeResult(funcName, args, convertNumber)
 +
self:assertEquals(expected, invokeResult)
 +
end
 +
 
 +
function suite:assertLuaAndInvokeTrue(trueFunc, funcName, args, convertNumber)
 +
args = args or {}
 +
local invokeResult = self:getInvokeResult(funcName, args, convertNumber)
 +
local luaResult = self.getLuaResult(funcName, args)
 +
self:assertTrue(trueFunc(invokeResult))
 +
self:assertTrue(trueFunc(luaResult))
 +
end
 +
 
 +
function suite:assertLuaAndInvokeEqual(funcName, testTable, convertNumber)
 +
local expected = testTable[1]
 +
local args = testTable[2] or {}
 +
self:assertLuaEquals(expected, funcName, args)
 +
self:assertInvokeEquals(expected, funcName, args, convertNumber)
 +
end
 +
 
 +
function suite:assertLuaAndInvokeEqualMany(funcName, testTables, convertNumber)
 +
for i, testTable in ipairs(testTables) do
 +
self:assertLuaAndInvokeEqual(funcName, testTable, convertNumber)
 +
end
 +
end
 +
 
 +
-------------------------------------------------------------------------------
 +
-- Test random
 +
-------------------------------------------------------------------------------
 +
 
 
function suite:test_random()
 
function suite:test_random()
    self:assertResultEquals ('{{#Invoke:math/sandbox|random', '}}', {
+
self:assertLuaAndInvokeTrue(function (n) return n >= 0 and n < 1 end, 'random')
    {'', '0.00047147460303804'},
+
self:assertLuaAndInvokeTrue(function (n) return n == 1 or n == 2 end, 'random', {2})
    {'|10','8'},
+
self:assertLuaAndInvokeTrue(function (n) return n >= 1 and n <= 10 and math.floor(n) == n end, 'random', {10})
    {'|1|2','2'},
+
self:assertLuaAndInvokeTrue(function (n) return n >= 10 and n <= 20 and math.floor(n) == n end, 'random', {10, 20})
    })
 
 
end
 
end
]]
+
 
 +
-------------------------------------------------------------------------------
 +
-- Test max
 +
-------------------------------------------------------------------------------
 
   
 
   
 
function suite:test_max()
 
function suite:test_max()
 
local tests = {
 
local tests = {
{'', ''},
+
{9, {5, 6, 9}},
{'', '|'},
+
{-5, {-5, -6, -9}},
{'9', '|5|6|9'},
 
{'-5', '|-5|-6|-9'},
 
 
}
 
}
for i, t in ipairs(tests) do
+
self:assertLuaAndInvokeEqualMany('max', tests)
self:assertResultEquals(t[1], invokeMath('max', t[2]))
+
self:assertLuaEquals(nil, 'max', {})
end
+
self:assertInvokeEquals('', 'max', {})
 
end
 
end
+
 
--[[
+
-------------------------------------------------------------------------------
 +
-- Test average
 +
-------------------------------------------------------------------------------
 +
 
 
function suite:test_average()
 
function suite:test_average()
    self:assertResultEquals ('{{#Invoke:math/sandbox|average|', '}}', {
+
local tests = {
    {'5|6|7', '6'},
+
{6, {5, 6, 7}},
    {'-7', '-7'},
+
{-7, {-7}},
    {'10000000001|10000000002|10000000003', '10000000002'},
+
{10000000002, {10000000001, 10000000002, 10000000003}},
    })
+
}
 +
self:assertLuaAndInvokeEqualMany('average', tests)
 
end
 
end
 
   
 
   
 +
-------------------------------------------------------------------------------
 +
-- Test min
 +
-------------------------------------------------------------------------------
 +
 
function suite:test_min()
 
function suite:test_min()
    self:assertResultEquals ('{{#Invoke:math/sandbox|min|', '}}', {
+
local tests = {
    {'',''},
+
{1, {1, 2, 3}},
    {'1|2|3','1'},
+
{-3, {-1, -2, -3}},
    {'-1|-2|-3','-3'},
+
}
    })
+
self:assertLuaAndInvokeEqualMany('min', tests)
 +
self:assertLuaEquals(nil, 'min', {})
 +
self:assertInvokeEquals('', 'min', {})
 
end
 
end
+
 
 +
-------------------------------------------------------------------------------
 +
-- Test gcd
 +
-------------------------------------------------------------------------------
 +
 
 +
function suite:test_gcd()
 +
local tests = {
 +
{4, {12, 8}},
 +
{2, {12, 8, 6}},
 +
{4, {-12, -8}},
 +
{2, {-12, -8, -6}},
 +
{8, {0, 8}},
 +
{8, {0, -8}},
 +
{0, {0}},
 +
{0, {0, 0}},
 +
{4, {12, nil, 8}},
 +
}
 +
self:assertLuaAndInvokeEqualMany('gcd', tests)
 +
end
 +
 
 +
-------------------------------------------------------------------------------
 +
-- Test order
 +
-------------------------------------------------------------------------------
 +
 
 
function suite:test_order()
 
function suite:test_order()
    self:assertResultEquals ('{{#Invoke:math/sandbox|order|', '}}', {
+
local tests = {
    {'2','0'},
+
{0, {2}},
    {'20','1'},
+
{1, {20}},
    {'200','2'},
+
{2, {200}},
    {'x = 5','0'},
+
{0, {5}},
    {'string','<strong class="error">Formatting error: Order of magnitude input appears non-numeric</strong>'},
+
}
})
+
self:assertLuaAndInvokeEqualMany('order', tests)
 +
self:assertInvokeEquals('<strong class="error">Formatting error: order of magnitude input appears non-numeric</strong>', 'order', {'string'})
 +
self:assertInvokeEquals(0, 'order', {x = 5})
 
end
 
end
+
 
 +
-------------------------------------------------------------------------------
 +
-- Test precision
 +
-------------------------------------------------------------------------------
 +
 
 
function suite:test_precison()
 
function suite:test_precison()
    self:assertResultEquals ('{{#Invoke:math/sandbox|precision|', '}}', {
+
local tests = {
{'1.9856', '4'},
+
{4, {1.9856}},
{'1.1', '1'},
+
{1, {1.1}},
{'1.9999999999', '10'},
+
{10, {1.9999999999}},
{'x = 1.9888', '4'},
+
}
{'letra', '<strong class="error">Formatting error: Precision input appears non-numeric</strong>'},
+
self:assertLuaAndInvokeEqualMany('precision', tests)
})
+
self:assertInvokeEquals('<strong class="error">Formatting error: precision input appears non-numeric</strong>', 'precision', {'letra'})
 +
self:assertInvokeEquals(4, 'precision', {x = '1.9888'})
 
end
 
end
+
 
 +
-------------------------------------------------------------------------------
 +
-- Test round
 +
-------------------------------------------------------------------------------
 +
 
 
function suite:test_round()
 
function suite:test_round()
    self:assertResultEquals ('{{#Invoke:math/sandbox|round|', '}}', {
+
local tests = {
{'1.99999', '2'},
+
{2, {1.99999}},
{'1.99999|0', '2'},
+
{2, {1.99999, 0}},
{'1.94|1', '1.9'},
+
{1.9, {1.94, 1}},
{'15|-1', '20'},
+
{20, {15, -1}},
{'value = 2.99999|precision = 2', '3'},
+
}
})
+
self:assertLuaAndInvokeEqualMany('round', tests)
 +
self:assertInvokeEquals(3, 'round', {value = '2.99999', precision = '2'})
 
end
 
end
+
 
 +
-------------------------------------------------------------------------------
 +
-- Test mod
 +
-------------------------------------------------------------------------------
 +
 
 +
function suite:test_mod()
 +
local tests = {
 +
{0, {10, 2}},
 +
{1, {11, 2}},
 +
{0, {525000000000000120000000000, 3}}, -- With the plain % operator this returns 68719476736 due to floating point error.
 +
}
 +
self:assertLuaAndInvokeEqualMany('mod', tests)
 +
self:assertInvokeEquals('<strong class="error">Formatting error: first argument to mod appears non-numeric</strong>', 'mod', {})
 +
self:assertInvokeEquals('<strong class="error">Formatting error: second argument to mod appears non-numeric</strong>', 'mod', {1})
 +
local successNoArgs = pcall(mm._mod)
 +
self:assertFalse(successNoArgs)
 +
local successOneArg = pcall(mm._mod, 1)
 +
self:assertFalse(successOneArg)
 +
end
 +
 
 +
-------------------------------------------------------------------------------
 +
-- Test precision format
 +
-------------------------------------------------------------------------------
 +
 
 
function suite:test_precison_format()
 
function suite:test_precison_format()
    self:preprocess_equals('{{#Invoke:math/sandbox|precision_format|10|2}}', '10.00')
+
local tests = {
 +
{'10.00', {10, 2}}
 +
}
 +
self:assertLuaAndInvokeEqualMany('precision_format', tests, false) -- the "false" stops string values being converted to numbers on re-entry from #invoke.
 +
end
 +
 
 +
-------------------------------------------------------------------------------
 +
-- Test cleanNumber
 +
-------------------------------------------------------------------------------
 +
 
 +
function suite:assertCleanNumberEquals(expectedTable, inputString)
 +
local expectedNum, expectedNumString = expectedTable[1], expectedTable[2]
 +
local actualNum, actualNumString = mm._cleanNumber(inputString)
 +
self:assertEquals(expectedNum, actualNum)
 +
self:assertEquals(expectedNumString, actualNumString)
 +
end
 +
 
 +
function suite:test_cleanNumber()
 +
self:assertCleanNumberEquals({0, '0'}, '0')
 +
self:assertCleanNumberEquals({1, '1'}, 1)
 +
self:assertCleanNumberEquals({2, '2'}, '  2  ')
 +
self:assertCleanNumberEquals({3, '3'}, '4-1')
 +
self:assertCleanNumberEquals({4, '4'}, '2 + 2')
 +
self:assertCleanNumberEquals({5, '5'}, '  2 + 3  ')
 +
self:assertCleanNumberEquals({6, '6'}, '+6')
 +
self:assertCleanNumberEquals({-7, '-7'}, '-7')
 +
self:assertCleanNumberEquals({88, '88'}, '0x58')
 +
self:assertCleanNumberEquals({1000000000, '1e+9'}, '1e+9')
 +
self:assertCleanNumberEquals({-88, '-88'}, '-0x58')
 +
self:assertCleanNumberEquals({0.16667, '0.16667'}, '1/6 round 5')
 +
self:assertCleanNumberEquals({nil, nil}, '1 foo 2') -- invalid expression
 +
self:assertCleanNumberEquals({nil, nil}, '1+') -- missing expr operand
 +
self:assertCleanNumberEquals({nil, nil}, '')
 +
self:assertCleanNumberEquals({nil, nil}, '  ')
 +
self:assertCleanNumberEquals({nil, nil}, 'string')
 +
self:assertCleanNumberEquals({nil, nil}, ' string with padding  ')
 
end
 
end
]]
+
 
 
 
return suite
 
return suite

Latest revision as of 07:55, 27 September 2020

Documentation for this module may be created at Module:Math/testcases/doc

-- Unit tests for [[Module:Math/sandbox]]. Click talk page to run tests.

local moduleName = 'Math/sandbox' -- assigning this to a variable as it is later used to generate an #invoke statement.
local mm = require('Module:' .. moduleName)
local ScribuntoUnit = require('Module:ScribuntoUnit')
local suite = ScribuntoUnit:new()

-------------------------------------------------------------------------------
-- Helper functions
-------------------------------------------------------------------------------

function suite.getLuaResult(funcName, args)
	args = args or {}
	local result = mm['_' .. funcName](unpack(args))
	return result
end

function suite:assertLuaEquals(expected, funcName, args)
	args = args or {}
	self:assertEquals(expected, self.getLuaResult(funcName, args))
end

function suite.buildInvocation(funcName, args)
	args = args or {}
	local argsClone = mw.clone(args)
	-- Build a module invocation equivalent to the args table. Taken from [[Module:Unsubst]].
	-- Numbered args first.
	local ret = '{{#invoke:' .. moduleName .. '|' .. funcName
	for k, v in ipairs(argsClone) do
		v = tostring(v)
		if string.find(v, '=', 1, true) then
			-- likely something like 1=foo=bar, we need to do it as a named arg
			break
		end
		ret = ret .. '|' .. v
		argsClone[k] = nil
	end
	for k, v in pairs(argsClone) do
		k = tostring(k)
		v = tostring(v)
		ret = ret .. '|' .. k .. '=' .. v
	end
	return ret .. '}}'
end

function suite:getInvokeResult(funcName, args, convertNumber) -- Unless convertNumber is false, the number is converted to a number, if possible, on re-entry to Lua.
	args = args or {}
	local invocation = self.buildInvocation(funcName, args)
	local result = self.frame:preprocess(invocation)
	if convertNumber ~= false and tonumber(result) then
		return tonumber(result)
	else
		return result
	end
end

function suite:assertInvokeEquals(expected, funcName, args, convertNumber)
	args = args or {}
	local invokeResult = self:getInvokeResult(funcName, args, convertNumber)
	self:assertEquals(expected, invokeResult)
end

function suite:assertLuaAndInvokeTrue(trueFunc, funcName, args, convertNumber)
	args = args or {}
	local invokeResult = self:getInvokeResult(funcName, args, convertNumber)
	local luaResult = self.getLuaResult(funcName, args)
	self:assertTrue(trueFunc(invokeResult))
	self:assertTrue(trueFunc(luaResult))
end

function suite:assertLuaAndInvokeEqual(funcName, testTable, convertNumber)
	local expected = testTable[1]
	local args = testTable[2] or {}
	self:assertLuaEquals(expected, funcName, args)
	self:assertInvokeEquals(expected, funcName, args, convertNumber)
end

function suite:assertLuaAndInvokeEqualMany(funcName, testTables, convertNumber)
	for i, testTable in ipairs(testTables) do
		self:assertLuaAndInvokeEqual(funcName, testTable, convertNumber)
	end
end

-------------------------------------------------------------------------------
-- Test random
-------------------------------------------------------------------------------

function suite:test_random()
	self:assertLuaAndInvokeTrue(function (n) return n >= 0 and n < 1 end, 'random')
	self:assertLuaAndInvokeTrue(function (n) return n == 1 or n == 2 end, 'random', {2})
	self:assertLuaAndInvokeTrue(function (n) return n >= 1 and n <= 10 and math.floor(n) == n end, 'random', {10})
	self:assertLuaAndInvokeTrue(function (n) return n >= 10 and n <= 20 and math.floor(n) == n end, 'random', {10, 20})
end

-------------------------------------------------------------------------------
-- Test max
-------------------------------------------------------------------------------
 
function suite:test_max()
	local tests = {
		{9, {5, 6, 9}},
		{-5, {-5, -6, -9}},
	}
	self:assertLuaAndInvokeEqualMany('max', tests)
	self:assertLuaEquals(nil, 'max', {})
	self:assertInvokeEquals('', 'max', {})
end

-------------------------------------------------------------------------------
-- Test average
-------------------------------------------------------------------------------

function suite:test_average()
	local tests = {
		{6, {5, 6, 7}},
		{-7, {-7}},
		{10000000002, {10000000001, 10000000002, 10000000003}},
	}
	self:assertLuaAndInvokeEqualMany('average', tests)
end
 
-------------------------------------------------------------------------------
-- Test min
-------------------------------------------------------------------------------

function suite:test_min()
	local tests = {
		{1, {1, 2, 3}},
		{-3, {-1, -2, -3}},
	}
	self:assertLuaAndInvokeEqualMany('min', tests)
	self:assertLuaEquals(nil, 'min', {})
	self:assertInvokeEquals('', 'min', {})
end

-------------------------------------------------------------------------------
-- Test gcd
-------------------------------------------------------------------------------

function suite:test_gcd()
	local tests = {
		{4, {12, 8}},
		{2, {12, 8, 6}},
		{4, {-12, -8}},
		{2, {-12, -8, -6}},
		{8, {0, 8}},
		{8, {0, -8}},
		{0, {0}},
		{0, {0, 0}},
		{4, {12, nil, 8}},
	}
	self:assertLuaAndInvokeEqualMany('gcd', tests)
end

-------------------------------------------------------------------------------
-- Test order
-------------------------------------------------------------------------------

function suite:test_order()
	local tests = {
		{0, {2}},
		{1, {20}},
		{2, {200}},
		{0, {5}},
	}
	self:assertLuaAndInvokeEqualMany('order', tests)
	self:assertInvokeEquals('<strong class="error">Formatting error: order of magnitude input appears non-numeric</strong>', 'order', {'string'})
	self:assertInvokeEquals(0, 'order', {x = 5})
end

-------------------------------------------------------------------------------
-- Test precision
-------------------------------------------------------------------------------

function suite:test_precison()
	local tests = {
		{4, {1.9856}},
		{1, {1.1}},
		{10, {1.9999999999}},
	}
	self:assertLuaAndInvokeEqualMany('precision', tests)
	self:assertInvokeEquals('<strong class="error">Formatting error: precision input appears non-numeric</strong>', 'precision', {'letra'})
	self:assertInvokeEquals(4, 'precision', {x = '1.9888'})
end

-------------------------------------------------------------------------------
-- Test round
-------------------------------------------------------------------------------

function suite:test_round()
	local tests = {
		{2, {1.99999}},
		{2, {1.99999, 0}},
		{1.9, {1.94, 1}},
		{20, {15, -1}},
	}
	self:assertLuaAndInvokeEqualMany('round', tests)
	self:assertInvokeEquals(3, 'round', {value = '2.99999', precision = '2'})
end

-------------------------------------------------------------------------------
-- Test mod
-------------------------------------------------------------------------------

function suite:test_mod()
	local tests = {
		{0, {10, 2}},
		{1, {11, 2}},
		{0, {525000000000000120000000000, 3}}, -- With the plain % operator this returns 68719476736 due to floating point error.
	}
	self:assertLuaAndInvokeEqualMany('mod', tests)
	self:assertInvokeEquals('<strong class="error">Formatting error: first argument to mod appears non-numeric</strong>', 'mod', {})
	self:assertInvokeEquals('<strong class="error">Formatting error: second argument to mod appears non-numeric</strong>', 'mod', {1})
	local successNoArgs = pcall(mm._mod)
	self:assertFalse(successNoArgs)
	local successOneArg = pcall(mm._mod, 1)
	self:assertFalse(successOneArg)
end

-------------------------------------------------------------------------------
-- Test precision format
-------------------------------------------------------------------------------

function suite:test_precison_format()
	local tests = {
		{'10.00', {10, 2}}
	}
	self:assertLuaAndInvokeEqualMany('precision_format', tests, false) -- the "false" stops string values being converted to numbers on re-entry from #invoke.
end

-------------------------------------------------------------------------------
-- Test cleanNumber
-------------------------------------------------------------------------------

function suite:assertCleanNumberEquals(expectedTable, inputString)
	local expectedNum, expectedNumString = expectedTable[1], expectedTable[2]
	local actualNum, actualNumString = mm._cleanNumber(inputString)
	self:assertEquals(expectedNum, actualNum)
	self:assertEquals(expectedNumString, actualNumString)
end

function suite:test_cleanNumber()
	self:assertCleanNumberEquals({0, '0'}, '0')
	self:assertCleanNumberEquals({1, '1'}, 1)
	self:assertCleanNumberEquals({2, '2'}, '  2  ')
	self:assertCleanNumberEquals({3, '3'}, '4-1')
	self:assertCleanNumberEquals({4, '4'}, '2 + 2')
	self:assertCleanNumberEquals({5, '5'}, '  2 + 3  ')
	self:assertCleanNumberEquals({6, '6'}, '+6')
	self:assertCleanNumberEquals({-7, '-7'}, '-7')
	self:assertCleanNumberEquals({88, '88'}, '0x58')
	self:assertCleanNumberEquals({1000000000, '1e+9'}, '1e+9')
	self:assertCleanNumberEquals({-88, '-88'}, '-0x58')
	self:assertCleanNumberEquals({0.16667, '0.16667'}, '1/6 round 5')
	self:assertCleanNumberEquals({nil, nil}, '1 foo 2') -- invalid expression
	self:assertCleanNumberEquals({nil, nil}, '1+') -- missing expr operand
	self:assertCleanNumberEquals({nil, nil}, '')
	self:assertCleanNumberEquals({nil, nil}, '  ')
	self:assertCleanNumberEquals({nil, nil}, 'string')
	self:assertCleanNumberEquals({nil, nil}, '  string with padding  ')
end

return suite