<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>https://cyclopedia.btz.alsace/index.php?action=history&amp;feed=atom&amp;title=Module%3AUnitTests</id>
	<title>Module:UnitTests - Historique des versions</title>
	<link rel="self" type="application/atom+xml" href="https://cyclopedia.btz.alsace/index.php?action=history&amp;feed=atom&amp;title=Module%3AUnitTests"/>
	<link rel="alternate" type="text/html" href="https://cyclopedia.btz.alsace/index.php?title=Module:UnitTests&amp;action=history"/>
	<updated>2026-04-11T22:39:38Z</updated>
	<subtitle>Historique des versions pour cette page sur le wiki</subtitle>
	<generator>MediaWiki 1.42.1</generator>
	<entry>
		<id>https://cyclopedia.btz.alsace/index.php?title=Module:UnitTests&amp;diff=263&amp;oldid=prev</id>
		<title>Admin : 1 version importée</title>
		<link rel="alternate" type="text/html" href="https://cyclopedia.btz.alsace/index.php?title=Module:UnitTests&amp;diff=263&amp;oldid=prev"/>
		<updated>2024-07-31T17:35:05Z</updated>

		<summary type="html">&lt;p&gt;1 version importée&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;fr&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Version précédente&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Version du 31 juillet 2024 à 17:35&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&quot; class=&quot;diff-notice&quot; lang=&quot;fr&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(Aucune différence)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key my_wiki:diff:1.41:old-262:rev-263 --&gt;
&lt;/table&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://cyclopedia.btz.alsace/index.php?title=Module:UnitTests&amp;diff=262&amp;oldid=prev</id>
		<title>wikipedia&gt;Aidan9382 : expected_actual should be based off of the expected, not the actual. This was basically seeing if actual == actual (which is always gonna be true). I&#039;ve also adjusted the variable name to be more accurate</title>
		<link rel="alternate" type="text/html" href="https://cyclopedia.btz.alsace/index.php?title=Module:UnitTests&amp;diff=262&amp;oldid=prev"/>
		<updated>2023-05-25T17:03:26Z</updated>

		<summary type="html">&lt;p&gt;expected_actual should be based off of the expected, not the actual. This was basically seeing if actual == actual (which is always gonna be true). I&amp;#039;ve also adjusted the variable name to be more accurate&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Nouvelle page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;-- UnitTester provides unit testing for other Lua scripts. For details see [[Wikipedia:Lua#Unit_testing]].&lt;br /&gt;
-- For user documentation see talk page.&lt;br /&gt;
local UnitTester = {}&lt;br /&gt;
&lt;br /&gt;
local frame, tick, cross, should_highlight&lt;br /&gt;
local result_table_header = &amp;quot;{|class=\&amp;quot;wikitable unit-tests-result\&amp;quot;\n|+ %s\n! !! Text !! Expected !! Actual&amp;quot;&lt;br /&gt;
local result_table_live_sandbox_header = &amp;quot;{|class=\&amp;quot;wikitable unit-tests-result\&amp;quot;\n|+ %s\n! !! Test !! Live !! Sandbox !! Expected&amp;quot;&lt;br /&gt;
&lt;br /&gt;
local result_table = { n = 0 }&lt;br /&gt;
local result_table_mt = {&lt;br /&gt;
	insert = function (self, ...)&lt;br /&gt;
		local n = self.n&lt;br /&gt;
		for i = 1, select(&amp;#039;#&amp;#039;, ...) do&lt;br /&gt;
			local val = select(i, ...)&lt;br /&gt;
			if val ~= nil then&lt;br /&gt;
				n = n + 1&lt;br /&gt;
				self[n] = val&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		self.n = n&lt;br /&gt;
	end,&lt;br /&gt;
	insert_format = function (self, ...)&lt;br /&gt;
		self:insert(string.format(...))&lt;br /&gt;
	end,&lt;br /&gt;
	concat = table.concat&lt;br /&gt;
}&lt;br /&gt;
result_table_mt.__index = result_table_mt&lt;br /&gt;
setmetatable(result_table, result_table_mt)&lt;br /&gt;
&lt;br /&gt;
local num_failures = 0&lt;br /&gt;
local num_runs = 0&lt;br /&gt;
&lt;br /&gt;
local function first_difference(s1, s2)&lt;br /&gt;
	s1, s2 = tostring(s1), tostring(s2)&lt;br /&gt;
    if s1 == s2 then return &amp;#039;&amp;#039; end&lt;br /&gt;
    local max = math.min(#s1, #s2)&lt;br /&gt;
    for i = 1, max do&lt;br /&gt;
        if s1:sub(i,i) ~= s2:sub(i,i) then return i end&lt;br /&gt;
    end&lt;br /&gt;
    return max + 1&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function return_varargs(...)&lt;br /&gt;
	return ...&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function UnitTester:calculate_output(text, expected, actual, options)&lt;br /&gt;
	-- Set up some variables for throughout for ease&lt;br /&gt;
	num_runs = num_runs + 1&lt;br /&gt;
	local options = options or {}&lt;br /&gt;
	&lt;br /&gt;
	-- Fix any stripmarkers if asked to do so to prevent incorrect fails&lt;br /&gt;
	local compared_expected = expected&lt;br /&gt;
	local compared_actual = actual&lt;br /&gt;
	if options.templatestyles then&lt;br /&gt;
		local pattern = &amp;#039;(\127[^\127]*UNIQ%-%-templatestyles%-)(%x+)(%-QINU[^\127]*\127)&amp;#039;&lt;br /&gt;
		local _, expected_stripmarker_id = compared_expected:match(pattern)				-- when module rendering has templatestyles strip markers, use ID from expected to prevent false test fail&lt;br /&gt;
		if expected_stripmarker_id then&lt;br /&gt;
			compared_actual = compared_actual:gsub(pattern, &amp;#039;%1&amp;#039; .. expected_stripmarker_id .. &amp;#039;%3&amp;#039;)	-- replace actual id with expected id; ignore second capture in pattern&lt;br /&gt;
			compared_expected = compared_expected:gsub(pattern, &amp;#039;%1&amp;#039; .. expected_stripmarker_id .. &amp;#039;%3&amp;#039;)		-- account for other strip markers&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if options.stripmarker then&lt;br /&gt;
		local pattern = &amp;#039;(\127[^\127]*UNIQ%-%-%l+%-)(%x+)(%-%-?QINU[^\127]*\127)&amp;#039;&lt;br /&gt;
		local _, expected_stripmarker_id = compared_expected:match(pattern)&lt;br /&gt;
		if expected_stripmarker_id then&lt;br /&gt;
			compared_actual = compared_actual:gsub(pattern, &amp;#039;%1&amp;#039; .. expected_stripmarker_id .. &amp;#039;%3&amp;#039;)&lt;br /&gt;
			compared_expected = compared_expected:gsub(pattern, &amp;#039;%1&amp;#039; .. expected_stripmarker_id .. &amp;#039;%3&amp;#039;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Perform the comparison&lt;br /&gt;
	local success = compared_actual == compared_expected&lt;br /&gt;
	if not success then&lt;br /&gt;
		num_failures = num_failures + 1&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Sort the wikitext for displaying the results&lt;br /&gt;
	if options.combined then&lt;br /&gt;
		-- We need 2 rows available for the expected and actual columns&lt;br /&gt;
		-- Top one is parsed, bottom is unparsed&lt;br /&gt;
		local differs_at = self.differs_at and (&amp;#039; \n| rowspan=2|&amp;#039; .. first_difference(compared_expected, compared_actual)) or &amp;#039;&amp;#039;&lt;br /&gt;
		-- Local copies of tick/cross to allow for highlighting&lt;br /&gt;
		local highlight = (should_highlight and not success and &amp;#039;style=&amp;quot;background:#fc0;&amp;quot; &amp;#039;) or &amp;#039;&amp;#039;&lt;br /&gt;
		result_table:insert(													-- Start output&lt;br /&gt;
			&amp;#039;| &amp;#039;, highlight, &amp;#039;rowspan=2|&amp;#039;, success and tick or cross,			-- Tick/Cross (2 rows)&lt;br /&gt;
			&amp;#039; \n| rowspan=2|&amp;#039;, mw.text.nowiki(text), &amp;#039; \n| &amp;#039;,					-- Text used for the test (2 rows)&lt;br /&gt;
			expected, &amp;#039; \n| &amp;#039;, actual,											-- The parsed outputs (in the 1st row)&lt;br /&gt;
			differs_at, &amp;#039; \n|-\n| &amp;#039;,											-- Where any relevant difference was (2 rows)&lt;br /&gt;
			mw.text.nowiki(expected), &amp;#039; \n| &amp;#039;, mw.text.nowiki(actual),			-- The unparsed outputs (in the 2nd row)&lt;br /&gt;
			&amp;#039;\n|-\n&amp;#039;															-- End output&lt;br /&gt;
		)&lt;br /&gt;
	else&lt;br /&gt;
		-- Display normally with whichever option was preferred (nowiki/parsed)&lt;br /&gt;
		local differs_at = self.differs_at and (&amp;#039; \n| &amp;#039; .. first_difference(compared_expected, compared_actual)) or &amp;#039;&amp;#039;&lt;br /&gt;
		local formatting = options.nowiki and mw.text.nowiki or return_varargs&lt;br /&gt;
		local highlight = (should_highlight and not success and &amp;#039;style=&amp;quot;background:#fc0;&amp;quot;|&amp;#039;) or &amp;#039;&amp;#039;&lt;br /&gt;
		result_table:insert(													-- Start output&lt;br /&gt;
			&amp;#039;| &amp;#039;, highlight, success and tick or cross,							-- Tick/Cross&lt;br /&gt;
			&amp;#039; \n| &amp;#039;, mw.text.nowiki(text), &amp;#039; \n| &amp;#039;,								-- Text used for the test&lt;br /&gt;
			formatting(expected), &amp;#039; \n| &amp;#039;, formatting(actual),					-- The formatted outputs&lt;br /&gt;
			differs_at,															-- Where any relevant difference was&lt;br /&gt;
			&amp;#039;\n|-\n&amp;#039;															-- End output&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function UnitTester:preprocess_equals(text, expected, options)&lt;br /&gt;
    local actual = frame:preprocess(text)&lt;br /&gt;
    self:calculate_output(text, expected, actual, options)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function UnitTester:preprocess_equals_many(prefix, suffix, cases, options)&lt;br /&gt;
    for _, case in ipairs(cases) do&lt;br /&gt;
        self:preprocess_equals(prefix .. case[1] .. suffix, case[2], options)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function UnitTester:preprocess_equals_preprocess(text1, text2, options)&lt;br /&gt;
	local actual = frame:preprocess(text1)&lt;br /&gt;
	local expected = frame:preprocess(text2)&lt;br /&gt;
	self:calculate_output(text1, expected, actual, options)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function UnitTester:preprocess_equals_compare(live, sandbox, expected, options)&lt;br /&gt;
	local live_text = frame:preprocess(live)&lt;br /&gt;
	local sandbox_text = frame:preprocess(sandbox)&lt;br /&gt;
	local highlight_live = false&lt;br /&gt;
	local highlight_sandbox = false&lt;br /&gt;
	num_runs = num_runs + 1&lt;br /&gt;
	if live_text == expected and sandbox_text == expected then&lt;br /&gt;
		result_table:insert(&amp;#039;| &amp;#039;, tick)&lt;br /&gt;
	else&lt;br /&gt;
		result_table:insert(&amp;#039;| &amp;#039;, cross)&lt;br /&gt;
		num_failures = num_failures + 1&lt;br /&gt;
&lt;br /&gt;
		if live_text ~= expected then&lt;br /&gt;
			highlight_live = true&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		if sandbox_text ~= expected then&lt;br /&gt;
			highlight_sandbox = true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
    local formatting = (options and options.nowiki and mw.text.nowiki) or return_varargs&lt;br /&gt;
    local differs_at = self.differs_at and (&amp;#039; \n| &amp;#039; .. first_difference(expected, live_text) or first_difference(expected, sandbox_text)) or &amp;#039;&amp;#039;&lt;br /&gt;
    result_table:insert(&lt;br /&gt;
			&amp;#039; \n| &amp;#039;,&lt;br /&gt;
			mw.text.nowiki(live),&lt;br /&gt;
			should_highlight and highlight_live and &amp;#039; \n|style=&amp;quot;background: #fc0;&amp;quot;| &amp;#039; or &amp;#039; \n| &amp;#039;,&lt;br /&gt;
			formatting(live_text),&lt;br /&gt;
			should_highlight and highlight_sandbox and &amp;#039; \n|style=&amp;quot;background: #fc0;&amp;quot;| &amp;#039; or &amp;#039; \n| &amp;#039;,&lt;br /&gt;
			formatting(sandbox_text),&lt;br /&gt;
			&amp;#039; \n| &amp;#039;,&lt;br /&gt;
			formatting(expected),&lt;br /&gt;
			differs_at,&lt;br /&gt;
			&amp;quot;\n|-\n&amp;quot;&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function UnitTester:preprocess_equals_preprocess_many(prefix1, suffix1, prefix2, suffix2, cases, options)&lt;br /&gt;
    for _, case in ipairs(cases) do&lt;br /&gt;
        self:preprocess_equals_preprocess(prefix1 .. case[1] .. suffix1, prefix2 .. (case[2] and case[2] or case[1]) .. suffix2, options)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function UnitTester:preprocess_equals_sandbox_many(module, function_name, cases, options)&lt;br /&gt;
    for _, case in ipairs(cases) do&lt;br /&gt;
		local live = module .. &amp;quot;|&amp;quot; .. function_name .. &amp;quot;|&amp;quot; .. case[1] .. &amp;quot;}}&amp;quot;&lt;br /&gt;
		local sandbox = module .. &amp;quot;/sandbox|&amp;quot; .. function_name .. &amp;quot;|&amp;quot; .. case[1] .. &amp;quot;}}&amp;quot;&lt;br /&gt;
        self:preprocess_equals_compare(live, sandbox, case[2], options)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function UnitTester:equals(name, actual, expected, options)&lt;br /&gt;
	num_runs = num_runs + 1&lt;br /&gt;
    if actual == expected then&lt;br /&gt;
        result_table:insert(&amp;#039;| &amp;#039;, tick)&lt;br /&gt;
    else&lt;br /&gt;
        result_table:insert(&amp;#039;| &amp;#039;, cross)&lt;br /&gt;
        num_failures = num_failures + 1&lt;br /&gt;
    end&lt;br /&gt;
    local formatting = (options and options.nowiki and mw.text.nowiki) or return_varargs&lt;br /&gt;
    local differs_at = self.differs_at and (&amp;#039; \n| &amp;#039; .. first_difference(expected, actual)) or &amp;#039;&amp;#039;&lt;br /&gt;
    local display = options and options.display or return_varargs&lt;br /&gt;
    result_table:insert(&amp;#039; \n| &amp;#039;, name, &amp;#039; \n| &amp;#039;,&lt;br /&gt;
    	formatting(tostring(display(expected))), &amp;#039; \n| &amp;#039;,&lt;br /&gt;
    	formatting(tostring(display(actual))), differs_at, &amp;quot;\n|-\n&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function deep_compare(t1, t2, ignore_mt)&lt;br /&gt;
    local ty1 = type(t1)&lt;br /&gt;
    local ty2 = type(t2)&lt;br /&gt;
    if ty1 ~= ty2 then return false end&lt;br /&gt;
    if ty1 ~= &amp;#039;table&amp;#039; and ty2 ~= &amp;#039;table&amp;#039; then return t1 == t2 end&lt;br /&gt;
&lt;br /&gt;
    local mt = getmetatable(t1)&lt;br /&gt;
    if not ignore_mt and mt and mt.__eq then return t1 == t2 end&lt;br /&gt;
&lt;br /&gt;
    for k1, v1 in pairs(t1) do&lt;br /&gt;
        local v2 = t2[k1]&lt;br /&gt;
        if v2 == nil or not deep_compare(v1, v2) then return false end&lt;br /&gt;
    end&lt;br /&gt;
    for k2, v2 in pairs(t2) do&lt;br /&gt;
        local v1 = t1[k2]&lt;br /&gt;
        if v1 == nil or not deep_compare(v1, v2) then return false end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function val_to_str(obj)&lt;br /&gt;
    local function table_key_to_str(k)&lt;br /&gt;
        if type(k) == &amp;#039;string&amp;#039; and mw.ustring.match(k, &amp;#039;^[_%a][_%a%d]*$&amp;#039;) then&lt;br /&gt;
            return k&lt;br /&gt;
        else&lt;br /&gt;
            return &amp;#039;[&amp;#039; .. val_to_str(k) .. &amp;#039;]&amp;#039;&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if type(obj) == &amp;quot;string&amp;quot; then&lt;br /&gt;
        obj = mw.ustring.gsub(obj, &amp;quot;\n&amp;quot;, &amp;quot;\\n&amp;quot;)&lt;br /&gt;
        if mw.ustring.match(mw.ustring.gsub(obj, &amp;#039;[^\&amp;#039;&amp;quot;]&amp;#039;, &amp;#039;&amp;#039;), &amp;#039;^&amp;quot;+$&amp;#039;) then&lt;br /&gt;
            return &amp;quot;&amp;#039;&amp;quot; .. obj .. &amp;quot;&amp;#039;&amp;quot;&lt;br /&gt;
        end&lt;br /&gt;
        return &amp;#039;&amp;quot;&amp;#039; .. mw.ustring.gsub(obj, &amp;#039;&amp;quot;&amp;#039;, &amp;#039;\\&amp;quot;&amp;#039; ) .. &amp;#039;&amp;quot;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    elseif type(obj) == &amp;quot;table&amp;quot; then&lt;br /&gt;
        local result, checked = {}, {}&lt;br /&gt;
        for k, v in ipairs(obj) do&lt;br /&gt;
            table.insert(result, val_to_str(v))&lt;br /&gt;
            checked[k] = true&lt;br /&gt;
        end&lt;br /&gt;
        for k, v in pairs(obj) do&lt;br /&gt;
            if not checked[k] then&lt;br /&gt;
                table.insert(result, table_key_to_str(k) .. &amp;#039;=&amp;#039; .. val_to_str(v))&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        return &amp;#039;{&amp;#039; .. table.concat(result, &amp;#039;,&amp;#039;) .. &amp;#039;}&amp;#039;&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
        return tostring(obj)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function UnitTester:equals_deep(name, actual, expected, options)&lt;br /&gt;
	num_runs = num_runs + 1&lt;br /&gt;
    if deep_compare(actual, expected) then&lt;br /&gt;
        result_table:insert(&amp;#039;| &amp;#039;, tick)&lt;br /&gt;
    else&lt;br /&gt;
        result_table:insert(&amp;#039;| &amp;#039;, cross)&lt;br /&gt;
        num_failures = num_failures + 1&lt;br /&gt;
    end&lt;br /&gt;
    local formatting = (options and options.nowiki and mw.text.nowiki) or return_varargs&lt;br /&gt;
    local actual_str = val_to_str(actual)&lt;br /&gt;
    local expected_str = val_to_str(expected)&lt;br /&gt;
    local differs_at = self.differs_at and (&amp;#039; \n| &amp;#039; .. first_difference(expected_str, actual_str)) or &amp;#039;&amp;#039;&lt;br /&gt;
    result_table:insert(&amp;#039; \n| &amp;#039;, name, &amp;#039; \n| &amp;#039;, formatting(expected_str),&lt;br /&gt;
    	&amp;#039; \n| &amp;#039;, formatting(actual_str), differs_at, &amp;quot;\n|-\n&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function UnitTester:iterate(examples, func)&lt;br /&gt;
	require &amp;#039;libraryUtil&amp;#039;.checkType(&amp;#039;iterate&amp;#039;, 1, examples, &amp;#039;table&amp;#039;)&lt;br /&gt;
	if type(func) == &amp;#039;string&amp;#039; then&lt;br /&gt;
		func = self[func]&lt;br /&gt;
	elseif type(func) ~= &amp;#039;function&amp;#039; then&lt;br /&gt;
		error((&amp;quot;bad argument #2 to &amp;#039;iterate&amp;#039; (expected function or string, got %s)&amp;quot;)&lt;br /&gt;
			:format(type(func)), 2)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	for i, example in ipairs(examples) do&lt;br /&gt;
		if type(example) == &amp;#039;table&amp;#039; then&lt;br /&gt;
			func(self, unpack(example))&lt;br /&gt;
		elseif type(example) == &amp;#039;string&amp;#039; then&lt;br /&gt;
			self:heading(example)&lt;br /&gt;
		else&lt;br /&gt;
			error((&amp;#039;bad example #%d (expected table, got %s)&amp;#039;)&lt;br /&gt;
				:format(i, type(example)), 2)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function UnitTester:heading(text)&lt;br /&gt;
	result_table:insert_format(&amp;#039; ! colspan=&amp;quot;%u&amp;quot; style=&amp;quot;text-align: left&amp;quot; | %s \n |- \n &amp;#039;,&lt;br /&gt;
		self.columns, text)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function UnitTester:run(frame_arg)&lt;br /&gt;
    frame = frame_arg&lt;br /&gt;
    self.frame = frame&lt;br /&gt;
    self.differs_at = frame.args[&amp;#039;differs_at&amp;#039;]&lt;br /&gt;
    tick = frame:preprocess(&amp;#039;{{Tick}}&amp;#039;)&lt;br /&gt;
    cross = frame:preprocess(&amp;#039;{{Cross}}&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
	local table_header = result_table_header&lt;br /&gt;
	if frame.args[&amp;#039;live_sandbox&amp;#039;] then&lt;br /&gt;
		table_header = result_table_live_sandbox_header&lt;br /&gt;
	end&lt;br /&gt;
	if frame.args.highlight then&lt;br /&gt;
		should_highlight = true&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	self.columns = 4&lt;br /&gt;
    if self.differs_at then&lt;br /&gt;
        table_header = table_header .. &amp;#039; !! Differs at&amp;#039;&lt;br /&gt;
        self.columns = self.columns + 1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Sort results into alphabetical order.&lt;br /&gt;
    local self_sorted = {}&lt;br /&gt;
    for key, _ in pairs(self) do&lt;br /&gt;
        if key:find(&amp;#039;^test&amp;#039;) then&lt;br /&gt;
            table.insert(self_sorted, key)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    table.sort(self_sorted)&lt;br /&gt;
    -- Add results to the results table.&lt;br /&gt;
    for _, value in ipairs(self_sorted) do&lt;br /&gt;
        result_table:insert_format(table_header .. &amp;quot;\n|-\n&amp;quot;, value)&lt;br /&gt;
        self[value](self)&lt;br /&gt;
        result_table:insert(&amp;quot;|}\n&amp;quot;)&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return (num_runs == 0 and &amp;quot;&amp;lt;b&amp;gt;No tests were run.&amp;lt;/b&amp;gt;&amp;quot;&lt;br /&gt;
    	or num_failures == 0 and &amp;quot;&amp;lt;b style=\&amp;quot;color:#008000\&amp;quot;&amp;gt;All &amp;quot; .. num_runs .. &amp;quot; tests passed.&amp;lt;/b&amp;gt;&amp;quot;&lt;br /&gt;
    	or &amp;quot;&amp;lt;b style=\&amp;quot;color:#800000\&amp;quot;&amp;gt;&amp;quot; .. num_failures .. &amp;quot; of &amp;quot; .. num_runs .. &amp;quot; tests failed.&amp;lt;/b&amp;gt;[[Category:Failed Lua testcases using Module:UnitTests]]&amp;quot;&lt;br /&gt;
    ) .. &amp;quot;\n\n&amp;quot; .. frame:preprocess(result_table:concat())&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function UnitTester:new()&lt;br /&gt;
    local o = {}&lt;br /&gt;
    setmetatable(o, self)&lt;br /&gt;
    self.__index = self&lt;br /&gt;
    return o&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local p = UnitTester:new()&lt;br /&gt;
function p.run_tests(frame) return p:run(frame) end&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>wikipedia&gt;Aidan9382</name></author>
	</entry>
</feed>