Module:UnitTests/doc

From Wikimedia Commons, the free media repository
Jump to navigation Jump to search

CodeDiscussionEditHistoryLinksLink count Subpages:DocumentationTestsResultsSandboxLive code All modules

This is the documentation page for Module:UnitTests

UnitTests provides a unit test facility that can be used by other scripts using require. See Wikipedia:Lua#Unit_testing for details. Following is a sample from Module:Bananas/testcases:

-- Unit tests for [[Module:Bananas]]. Click talk page to run tests.
local p = require('Module:UnitTests')

function p:test_hello()
    self:preprocess_equals('Hello, world!', 'Hello, world!')
end

return p

The talk page Module talk:Bananas/testcases executes it with {{#invoke: Bananas/testcases | run_tests}}. Test methods like test_hello above must begin with "test".

Methods[edit]

run_tests[edit]

  • run_tests: Runs all tests. Normally used on talk page of unit tests.
    {{#invoke:Bananas/testcases|run_tests}}
  • If differs_at=1 is specified, a column will be added showing the first character position where the expected and actual results differ.
    {{#invoke:Bananas/testcases|run_tests|differs_at=1}}

The test methods below that also accept an optional options parameter which can give processing instructions for the results. If this parameter is used, it must be a Lua table. The following fields in that table are recognized:

  • varying=1 : any non-nil and non-false value allows the test to be executed, and both expected and actual values are compared; but if there's a difference, we'll see the warning icon ⚠[!] instead of the failure icon ✘[No]: this test is still counted as successful and not as a failure when results are different; when the results are identical, you still see the success icon ✓[OK]. This is useful for example when checking the result of a test whose output is constantly changing (e.g. a function that returns a random value), or for comparing the actual results of a tested module with the results of an legacy template or module implementing a new better behavior that was purposely changed.
  • nowiki=1 : any non-nil and non-false value allows displaying expected and actual results in plain text form where its content will not be preprocessed by MediaWiki. Useful for tests that generate external links or links to images or videos and other complex formats, or that include named or numeric character entities for characters (such as ' ', ' ', or ' ', or ' ') which could be equivalently encoded using plain UTF-8 (such as ' ' for the non-breaking space NBSP, which may also be encoded in a Lua string constant provided for the expected value by using decimal escapes for each byte of the UTF-8 sequence, such as '\194\160' or other Lua escapes, or directly in plain text if they are not controls, reserved in the Lua syntax for string delimiters) with the same rendering in HTML. It also allows defining the expected value string more easily for designing tests providing an explicit one.
    Note that strings compared in Lua are independant of the HTML or MediaWiki parsing and independant of the UTF-8 encoding implicitly used by MediaWiki, so named or numeric character entities are considered to be distinct from plain-text encoding; but the plain-text UTF-8 encoding of string constants (when it is permitted by the syntax) is equivalent to encodings using Lua escapes (starting by \).
  • htmlize=1 : any non-nil and non-false value is similar to nowiki=1 but allows expected and actual results in plain wikitext form, where its content will not be preprocessed by MediaWiki, but where also the HTML tags and attributes, HTML comments, and other MediaWiki magic keywords or the MediaWiki wiki syntax for tables, lists, and images will not be postprocessed by Mediawiki, showing the wikitext exactly as it is generated. In addition, the ampersand character & (also used in HTML characters entities) will be rendered as &, and plaintext whitespaces will be rendered in the displayed plaintext as numeric HTML character entities (	 for TAB, 
 for NEWLINE,   for the ASCII SPACE,   for NBSP) so that different encodings in the generated output can be easily distringuished visually and that the Mediawiki postprocessing (from Wikitext to HTML) will not strip or compress these whitespaces, and will not reorder them outside embedded HTML elements (when tidying its HTML output).
  • asciionly=1 : any non-nil and non-false value allows displaying expected and actual results with all non-ASCII characters replaced by their UTF-8 encoding rendered byte per byte in decimal with Lua escapes (like \194\160 for a plain-text non-breaking space). This does not transform HTML escapes, but this can be combined with nowiki=1 or htmlize=1. Useful for debugging purpose when invalid UTF-8 sequences are generated by the code to test, or to help locating in the results invisible controls and or valid Unicode codepoints forbidden in HTML, all of these would not be displayed correctly in the results.
  • some test methods below accept additional options.

heading[edit]

  • self:heading(text): generates an additional row in the results table, displaying some arbitrary text spanning all columns of the table. The text may contain wiki markup. Can be useful to describe the test of the meaning of "Actual" and "Expected" columns in the generated results table. Can also be used to describe a subgroup of individual tests executed and rendered in the following rows of results.

preprocess_equals[edit]

  • self:preprocess_equals(text, expected, options): Gives a piece of wikitext to preprocess and an expected resulting value. Scripts and templates can be invoked in the same manner they would be in a page.
    self:preprocess_equals('{{#invoke:Bananas | hello}}', 'Hello, world!', {nowiki=1})

preprocess_equals_many[edit]

  • preprocess_equals_many(prefix, suffix, cases, options): Performs a series of preprocess_equals() calls on a set of given pairs. Automatically adds the given prefix and suffix to each text.
    self:preprocess_equals_many(
        '{{#invoke:BananasArgs|add|', '}}',
        {
            { '2|3', '5' },
            { '-2|2', '0' },
        }
    )
    self:preprocess_equals_many(
        '{{#invoke:Coordinates/sandbox|externalLink|site=', '}}',
        {
            { 'GoogleMaps|globe=Mars|lat=-14.6|lon=175.5',
              '//www.google.com/mars/#lat=-14.6&lon=175.5&zoom=8'
            },
            { 'GeoHack|globe=Moon|lat=0.655930|lon=23.470173|lang=en',
              '//geohack.toolforge.org/geohack.php?pagename=Module_talk:Coordinates/sandbox/testcases&params=0.655930_N_23.470173_E_globe:Moon_&language=en'
            },
        }
    )
    self:preprocess_equals_many(
        '{{#invoke:Coordinates/sandbox|GeoHack_link|lat=51.48|lon=0|lang=', '}}',
        {
            { 'en',
              '<span class="plainlinksneverexpand">[//geohack.toolforge.org/geohack.php?pagename=Module_talk:Coordinates/sandbox/testcases&params=51.48_N_0_E_globe:Earth_&language=en 51°&nbsp;28′&nbsp;48″&nbsp;N, 0°&nbsp;00′&nbsp;00″&nbsp;E]</span>'
            },
            { 'ru',
              '<span class="plainlinksneverexpand">[//geohack.toolforge.org/geohack.php?pagename=Module_talk:Coordinates/sandbox/testcases&params=51.48_N_0_E_globe:Earth_&language=ru 51°&nbsp;28′&nbsp;48″&nbsp;с.&nbsp;ш., 0°&nbsp;00′&nbsp;00″&nbsp;в.&nbsp;д.]</span>'
            },
        },
        -- nowiki disables the MediaWiki expansion of templates, so that results also display the generated wikitexts (including wikilinks, categories, wikitables,
        -- wikilists, HTML tags and attributes, magic keywords), without postprocessing them to HTML (such as transforming external links with an additional icons)
        { nowiki = 1 }
    )

preprocess_equals_many_same[edit]

  • preprocess_equals_many_same(prefix, suffix, cases, expected, options): Performs a series of preprocess_equals() calls on a set of input cases with the same expected output. Automatically adds the given prefix and suffix to each text.
    self:preprocess_equals_many(
        '{{#invoke:BananasArgs|add|', '}}',
        {
            '2|3',
            '3|2',
            '10|-5',
        },
        '5',
        -- options here are not necessary, given the format of the expected output above
        { nowiki = 1 }
    )

preprocess_equals_preprocess[edit]

  • self:preprocess_equals_preprocess(text, expected, options): Gives two pieces of wikitext to preprocess and determines if they produce the same value. Useful for comparing scripts to existing templates.
    self:preprocess_equals_preprocess(
        '{{#invoke:Bananas | hello}}',
        '{{Hello}}',
         -- nowiki doesn't prevent the template expansion of '{{Hello}}' by MediaWiki, as the expected and actual results are preprocessed,
         -- but it shows the wikitext with tags and attributes generated in the MediaWiki syntax, without rendering it as normal HTML.
        { nowiki = 1 }
    )

preprocess_equals_preprocess_many[edit]

  • self:preprocess_equals_preprocess_many(prefix, suffix, cases, options): Performs a series of preprocess_equals_preprocess() calls on a set of given pairs. The prefix/suffix supplied for both arguments is added automatically. If in any case the second part is not specified, the first part will be used.
    self:preprocess_equals_preprocess_many(
        '{{#invoke:Foo | spellnum |', '}}',
        '{{spellnum', '}}',
        {
          { '2' }, -- equivalent to {'2','2'},
          { '-2', '-2.0' },
        },
        -- options here are not necessary, given the format of the expected outputs above
        { nowiki = 1 }
    )

equals[edit]

  • self:equals(name, actual, expected, options): Gives a computed value and the expected value, and checks if they are equal according to the == operator. Useful for testing modules that are designed to be used by other modules rather than using #invoke.
This is intended to perform tests using calls internal in Lua, without preprocessing the input text for the actual value as if it was a MediaWiki syntax. The test actual value provided as a Lua expression.
Now equals() allows comparing results independantly of their type, and even allows checking circular references in tables and to check them.
In such case, special reference values are inserted, containing the datatype name, an hash sign and an ordinal id (such as :table#2: for a reference to the 2nd table in the result, tables basing counted from their opening [ character in the result).
Metatables attached to tables (if they are set) may also be dumped and compared using an empty key []. For that you must set the option include_mt to include metatables in the expected and actual results.
It works even when datatypes are different, between numbers, booleans, strings, tables, functions or nil.
It also works when keys have different types, or there are integer keys out of sequence; keys in tables are sorted in a stable order (starting by integer keys in sequence 1..N, then other integers, booleans, strings, tables, references to functions, other references).
    self:equals('Simple addition', 2 + 2, 4)
    self:equals('Simple equality test', 2 == 2, true)
    self:equals('Test returning tables',
        {{2 == 2}},
        {{true}},
        -- The nowiki option avoids MediaWiki postprocessing of Lua tables as if it was a Mediawiki syntax to expand a template.
        {nowiki=1}
    )
    self:equals('Test returning HTML',
        mw.html.create('span'):css('display', 'none'):wikitext('dummy'):tostring(),
        '<span style="display:none">dummy</span>',
        -- The nowiki option avoids MediaWiki postprocessing to HTML (that would be invisible in the expected and actual values shown in the results table)
        {nowiki=1}
    )

equals_deep[edit]

  • self:equals_deep(name, actual, expected, options): Like equals, but handles tables by doing a deep comparison. Neither value should contain circular references, as they are not handled by the current implementation and may result in an infinite loop.
Legacy, now fully equivalent to equals(). The old restriction of use shown above no longer applies and you can compare Lua values with any type, including tables with circular references either in their keys, mapped values, or assigned metatables.
    self:equals_deep('Table comparison', createRange(1,3), {1,2,3}, {nowiki=1}) -- legacy
    self:equals('Table comparison', createRange(1,3), {1,2,3}, {nowiki=1}) -- now equivalent

See also[edit]