请输入您要查询的百科知识:

 

词条 Module:Convert/tester
释义 -- Test the output from a template by comparing it with fixed text.-- The expected text must be in a single line, but can include-- "\" (two characters) to indicate that a newline is expected.-- Tests are run (or created) by setting p.tests (string or table), or-- by setting page=PAGE_TITLE (and optionally section=SECTION_TITLE),-- then executing run_tests (or make_tests).

local function collection()

-- Return a table to hold lines of text.

return {

n = 0,

add = function (self, s)

self.n = self.n + 1

self[self.n] = s

end,

join = function (self, sep)

return table.concat(self, sep)

end,

}

end

local function empty(text)

-- Return true if text is nil or empty (assuming a string).

return text == nil or text ==

end

local function strip(text)

-- Return text with no leading/trailing whitespace.

return text:match("^%s*(.-)%s*$")

end

local function status_box(stats, expected, actual, iscomment)

local label, bgcolor, align, isfail

if iscomment then

actual =

align = 'center'

bgcolor = 'silver'

label = 'Cmnt'

elseif expected == then

stats.ignored = stats.ignored + 1

return , actual

elseif expected == actual then

stats.pass = stats.pass + 1

actual =

align = 'center'

bgcolor = 'green'

label = 'Pass'

else

stats.fail = stats.fail + 1

align = 'center'

bgcolor = 'red'

label = 'Fail'

isfail = true

end

local sbox = 'style="text-align:' .. align .. ';color:white;background:' .. bgcolor .. ';" | ' .. label

return sbox, actual, isfail

end

local function status_text(stats)

local bgcolor, ignored_text, msg

if stats.fail == 0 then

if stats.pass == 0 then

bgcolor = 'salmon'

msg = 'No tests performed'

else

bgcolor = 'green'

msg = string.format('All %d tests passed', stats.pass)

end

else

bgcolor = 'darkred'

msg = string.format('%d test%s failed', stats.fail, stats.fail == 1 and or 's')

end

if stats.ignored == 0 then

ignored_text =

else

bgcolor = 'salmon'

ignored_text = string.format(', %d test%s ignored because expected text is blank', stats.ignored, stats.ignored == 1 and or 's')

end

return '' .. msg .. ignored_text .. '.'

end

local function run_template(frame, template, args, collapse_multiline)

-- Template "{{ example | 2 = def | abc | name = ghi jkl }}"

-- gives xargs { " abc ", "def", name = "ghi jkl" }.

if template:sub(1, 2) == '{{' and template:sub(-2, -1) == '}}' then

template = template:sub(3, -3) .. '|' -- append sentinel to get last field

else

return '(invalid template)'

end

local xargs = {}

local index = 1

local templatename

local function put_arg(k, v)

-- Kludge: Module:Val uses Module:Arguments which trims arguments and

-- omits blank arguments. Simulate that here.

-- LATER Need a parameter to control this.

if templatename:sub(1, 3) == 'val' then

v = strip(v)

if v == then

return

end

end

xargs[k] = v

end

template = template:gsub('(%[%^%[%-)|(.-%]%])', '%1\\0%2') -- replace pipe in piped link with a zero byte

for field in template:gmatch('(.-)|') do

field = field:gsub('%z', '|') -- restore pipe in piped link

if templatename == nil then

templatename = args.template or strip(field)

if templatename == then

return '(invalid template)'

end

else

local k, eq, v = field:match("^(.-)(=)(.*)$")

if eq then

k, v = strip(k), strip(v) -- k and/or v can be empty

local i = tonumber(k)

if i and i > 0 and string.match(k, '^%d+$') then

put_arg(i, v)

else

put_arg(k, v)

end

else

while xargs[index] ~= nil do

-- Skip any explicit numbered parameters like "|5=five".

index = index + 1

end

put_arg(index, field)

end

end

end

if args.test and not xargs.test then

-- For convert, allow test=preview or test=nopreview to be injected into

-- the convert under test, if it does not already use that parameter.

-- That allows, for example, a preview of make_tests to show nopreview results.

xargs.test = args.test

end

local function expand(t)

return frame:expandTemplate(t)

end

local ok, result = pcall(expand, { title = templatename, args = xargs })

if not ok then

result = 'Error: ' .. result

end

if collapse_multiline then

result = result:gsub('\', '\\\')

end

return result

end

local function _make_tests(frame, all_tests, args)

local maxlen = 38

for _, item in ipairs(all_tests) do

local template = item[1]

if template then

local templen = mw.ustring.len(template)

item.templen = templen

if maxlen < templen and templen <= 70 then

maxlen = templen

end

end

end

local result = collection()

for _, item in ipairs(all_tests) do

local template = item[1]

if template then

local actual = run_template(frame, template, args, true)

local pad = string.rep(' ', maxlen - item.templen) .. ' '

result:add(template .. pad .. actual)

else

local text = item.text

if text then

result:add(text)

end

end

end

-- Pre tags returned by a module are html tags, not like wikitext

...
.

return '

\' .. mw.text.nowiki(result:join('\')) .. '\
'

end

local function _run_tests(frame, all_tests, args)

local function safe_cell(text, multiline)

-- For testing {{convert}}, want wikitext like 'kg' to be unchanged

-- so the link works and so the displayed text is short (just "kg" in example).

text = text:gsub('(%[%^%[%-)|(.-%]%])', '%1\\0%2') -- replace pipe in piped link with a zero byte

text = text:gsub('{', '{'):gsub('|', '|') -- escape '{' and '|'

text = text:gsub('%z', '|') -- restore pipe in piped link

if multiline then

text = text:gsub('\\\', '
')

end

return text

end

local function nowiki_cell(text, multiline)

text = mw.text.nowiki(text)

if multiline then

text = text:gsub('\\\', '
')

end

return text

end

local stats = { pass = 0, fail = 0, ignored = 0 }

local result = collection()

result:add('{| class="wikitable"')

result:add('! Template !! Expected !! Actual, if different !! Status')

for _, item in ipairs(all_tests) do

local template, expected = item[1], item[2] or

if template then

local actual = run_template(frame, template, args, true)

local sbox, actual, isfail = status_box(stats, expected, actual)

result:add('|-')

result:add('| ' .. safe_cell(template))

result:add('| ' .. safe_cell(expected, true))

result:add('| ' .. safe_cell(actual, true))

result:add('| ' .. sbox)

if isfail then

result:add('|-')

result:add('| align="center"| (above, nowiki)')

result:add('| ' .. nowiki_cell(expected, true))

result:add('| ' .. nowiki_cell(actual, true))

result:add('|')

end

else

local text = item.text

if text and text:sub(1, 3) == '---' then

result:add('|-')

result:add('| colspan="3" style="color:white;background:silver;" | ' .. safe_cell(strip(text:sub(4)), true))

result:add('| ' .. status_box(stats, , , true))

end

end

end

result:add('|}')

return status_text(stats) .. '\\' .. result:join('\')

end

local function get_page_content(page_title, ignore_error)

local t = mw.title.new(page_title)

if t then

local content = t:getContent()

if content then

if content:sub(-1) ~= '\' then

content = content .. '\'

end

return content

end

end

if not ignore_error then

error('Could not read wikitext from "' .. page_title .. '".', 0)

end

end

local function _compare(frame, page_pairs)

local function diff_link(title1, title2)

return '[' ..

tostring(mw.uri.fullUrl('Special:ComparePages',

{ page1 = title1, page2 = title2 })) ..

' diff]'

end

local function link(title)

return '' .. title .. ''

end

local function message(text, isgood)

local color = isgood and 'green' or 'darkred'

return '' .. text .. ''

end

local result = collection()

for _, item in ipairs(page_pairs) do

local label

local title1 = item[1]

local title2 = item[2]

if title1 == title2 then

label = message('same title', false)

else

local content1 = get_page_content(title1, true)

local content2 = get_page_content(title2, true)

if not content1 or not content2 then

label = message('does not exist', false)

elseif content1 == content2 then

label = message('same content', true)

else

label = message('different', false) .. ' (' .. diff_link(title1, title2) .. ')'

end

end

result:add('*' .. link(title1) .. ' • ' .. link(title2) .. ' • ' .. label)

end

return result:join('\')

end

local function sections(text)

return {

first = 1, -- just after the newline at the end of the last heading

this_section = 1,

next_heading = function(self)

local first = self.first

while first <= #text do

local last, heading

first, last, heading = text:find('==+[\\t ]*([^\]-)[\\t ]*==+[\\t\\r ]*\', first)

if first then

if first == 1 or text:sub(first - 1, first - 1) == '\' then

self.this_section = first

self.first = last + 1

return heading

end

first = last + 1

else

break

end

end

self.first = #text + 1

return nil

end,

current_section = function(self)

local first = self.this_section

local last = text:find('\==[^\]-==[\\t\\r ]*\', first)

if not last then

last = -1

end

return text:sub(first, last)

end,

}

end

local function get_tests(frame, tests)

local args = frame.args

local page_title, section_title = args.page, args.section

local show_all = (args.show == 'all')

if not empty(page_title) then

if not empty(tests) then

error('Invoke must not set "page=' .. page_title .. '" if also setting p.tests.', 0)

end

if page_title:sub(1, 2) == 'sub(-2) == '' then

page_title = strip(page_title:sub(3, -3))

end

tests = get_page_content(page_title)

if not empty(section_title) then

local s = sections(tests)

while true do

local heading = s:next_heading()

if heading then

if heading == section_title then

tests = s:current_section()

break

end

else

error('Section "' .. section_title .. '" not found in page ' .. page_title .. '.', 0)

end

end

end

end

if type(tests) ~= 'string' then

if type(tests) == 'table' then

return tests

end

error('No tests were specified; see Convert/tester/doc.', 0)

end

if tests:sub(-1) ~= '\' then

tests = tests .. '\'

end

local template_count = 0

local all_tests = collection()

for line in (tests):gmatch('([^\]-)[\\t\\r ]*\') do

local template, expected = line:match('^({{.-}})%s*(.-)%s*$')

if template then

template_count = template_count + 1

all_tests:add({ template, expected })

elseif show_all then

all_tests:add({ text = line })

end

end

if template_count == 0 then

error('No templates found; see Convert/tester/doc.', 0)

end

return all_tests

end

local function main(frame, p, worker)

local ok, result = pcall(get_tests, frame, p.tests)

if ok then

ok, result = pcall(worker, frame, result, frame.args)

if ok then

return result

end

end

return 'Error\\' .. result

end

local modules = {

-- For convenience, a key defined here can be used to refer to the

-- corresponding list of modules.

countries = { -- Commons

'Countries',

'Countries/Africa',

'Countries/Americas',

'Countries/Arab world',

'Countries/Asia',

'Countries/Caribbean',

'Countries/Central America',

'Countries/Europe',

'Countries/North America',

'Countries/North America (subcontinent)',

'Countries/Oceania',

'Countries/South America',

'Countries/United Kingdom',

},

convert = {

'Convert',

'Convert/data',

'Convert/text',

'Convert/extra',

'Convert/wikidata',

'Convert/wikidata/data',

},

cs1 = {

'Citation/CS1',

'Citation/CS1/Configuration',

},

cs1all = {

'Citation/CS1',

'Citation/CS1/Configuration',

'Citation/CS1/Whitelist',

'Citation/CS1/Date validation',

},

team = {

'Team appearances list',

'Team appearances list/data',

'Team appearances list/show',

},

val = {

'Val',

'Val/units',

},

}

local p = {}

function p.compare(frame)

local page_pairs = p.pairs

if not page_pairs then

local args = frame.args

if not args[2] then

local builtins = modules[args[1] or 'convert']

if builtins then

args = builtins

end

end

page_pairs = {}

for i, title in ipairs(args) do

if not title:find(':', 1, true) then

title = 'Module:' .. title

end

page_pairs[i] = { title, title .. '/sandbox' }

end

end

local ok, result = pcall(_compare, frame, page_pairs)

if ok then

return result

end

return 'Error\\' .. result

end

p.check_sandbox = p.compare

function p.make_tests(frame)

return main(frame, p, _make_tests)

end

function p.run_tests(frame)

return main(frame, p, _run_tests)

end

return p

随便看

 

开放百科全书收录14589846条英语、德语、日语等多语种百科知识,基本涵盖了大多数领域的百科知识,是一部内容自由、开放的电子版国际百科全书。

 

Copyright © 2023 OENC.NET All Rights Reserved
京ICP备2021023879号 更新时间:2024/9/30 5:23:58