Jump to content

Extension:MWUnit/Test doubles

From mediawiki.org

Sometimes it is difficult to test certain templates because they rely on other templates or components that cannot be used in the test environment. This could be because they will not return the results needed or because executing those templates would have undesirable side effects.

When writing tests, we can replace templates and parser with test doubles, or 'mocks'. These templates and parser functions provide the same API as the original template, but their output is controlled via the test.

Mocking templates

[edit]

The #create_mock parser function replaces the given template with our mock content.

<setup>
{{#create_mock: Foobar | Boofar }} <!-- Mock the template Foobar to return "Boofar" -->
</setup>

<testcase name="foo" group="bar">
{{Foobar}} <!-- Boofar -->
...
</testcase>

It is also possible to mock pages in other namespaces:

<setup>
{{#create_mock: :Main Page | Boofar }} <!-- Mock the Main Page to return "Boofar" -->
</setup>

<testcase name="foo" group="bar">
{{:Main Page}} <!-- Boofar -->
...
</testcase>

The content of the mock is only parsed whenever the template is used and can therefore contain template specific syntax. If we want a mock to return its first argument, we can do the following:

{{#create_mock: Foobar | {{{1}}} }} <!-- Mock the template to return the first argument -->

<testcase name="foo" group="bar">
{{Foobar|Boofar}} <!-- Boofar -->
...
</testcase>

Whenever a mocked page is transcluded in a test, the actual content of the page will be ignored and will be replaced with the mocked content. It is only possible to mock existing pages. Mocking a page that does not exist will result in an error.

Mocking parser functions

[edit]

The #create_parser_mock parser function is used to overwrite the callback for parser functions. The first parameter of this parser function takes the name of the parser function, without the hashtag. The second parameter of this parser function takes the content which should be returned when this parser function is called. This content is processed to have the same variable interface as templates:

<setup>
{{#create_parser_mock: tag | foobar }}
</setup>

<testcase name="foo" group="bar">
{{#tag: baz}} <!-- Returns "foobar" instead of "<baz/>" -->
...
</testcase>
<setup>
{{#create_parser_mock: tag | {{{baz}}} }}
</setup>

<testcase name="foo" group="bar">
{{#tag: baz=foobar}} <!-- The mock content is processed and the {{{baz}}} is appropriately replaced with "foobar" -->

...

{{#create_parser_mock: tag | {{{1}}} }} <!-- Count starts at `1` -->
{{#tag: foobar}} <!-- foobar -->
</testcase>

See also

[edit]