Module:ScribuntoUnit/doc: Difference between revisions

From Path of Exile Wiki
Jump to navigation Jump to search
>OmegaK2
m (1 revision)
No edit summary
 
(8 intermediate revisions by 3 users not shown)
Line 1: Line 1:
This module provides [[unit test]]s for other [[WP:Lua|Lua]] modules. To test a module, you must create a separate test module, usually located at <code>Module:''Module name''/testcases</code>. The module is tested with the ScribuntoUnit module, which verifies that the operations defined in the test module produce the expected results.
{{Documentation subpage}}


== Test module structure ==
{{Lua|Module:ScribuntoUnit/config}}


This module provides [[wikipedia:Unit testing|unit tests]] for other [[gphelp:Extension:Scribunto|Scribunto]] modules. To test a module, you must create a separate testing module, usually located on the module's /testcases subpage. The testing module uses ScribuntoUnit to verify that the operations defined in it produce the expected results.
==Test module structure==
To make a test module (test suite), start with the following code:
To make a test module (test suite), start with the following code:


<source lang="lua">
<syntaxhighlight lang="lua">
local myModule = require('Module:MyModule') -- the module to be tested
local myModule = require('Module:MyModule') -- the module to be tested
local ScribuntoUnit = require('Module:ScribuntoUnit')
local ScribuntoUnit = require('Module:ScribuntoUnit')
local suite = ScribuntoUnit:new()
local suite = ScribuntoUnit:new()
</source>
</syntaxhighlight>


After you have done this you can add individual test functions to the <code>suite</code> object. Any function that begins with <code>test</code> is treated as a test. (Other functions will be ignored by ScribuntoUnit, but can be used in the tests themselves.)
After you have done this you can add individual test functions. Any member function of the <code>suite</code> object that has a name beginning with "test" is treated as a test by ScribuntoUnit.


<source lang="lua">
<syntaxhighlight lang="lua">
function suite:testSomeCall()
function suite:testSomeCall()
     self:assertEquals('expected value', myModule.someCall(123))
     self:assertEquals('expected value', myModule.someCall(123))
Line 23: Line 26:
     self:assertEquals('other expected value', myModule.someOtherCall(456))
     self:assertEquals('other expected value', myModule.someOtherCall(456))
end
end
</source>
</syntaxhighlight>


The tests you write should make assertions, and ScribuntoUnit will check whether those assertions are true. For example, <code>assertEquals</code> checks that both of the arguments it is given are equal. If ScribuntoUnit doesn't find an assertion to be true, then the test will fail and an error message will be generated. The error message will show which assertion failed verification (other checks on the assertions are not made at this time).
The tests you write should make assertions, and ScribuntoUnit will check whether those assertions are true. For example, <code>assertEquals</code> checks that both of the arguments it is given are equal. If ScribuntoUnit doesn't find an assertion to be true, then the test will fail and an error message will be generated. The error message will show which assertion failed verification. (Other checks on the assertions are not made at this time.)


To finish the test module, you need to return the <code>suite</code> object.
The return value of the test module should be the <code>suite</code> object.


<source lang="lua">
<syntaxhighlight lang="lua">
return suite
return suite
</source>
</syntaxhighlight>


== Running the tests ==
==Running the tests==
When implemented correctly with ScribuntoUnit, the testing module located on a module's /testcases subpage will run automatically and display the results.


The tests can be run in two ways: through the Lua debug console, and from a wiki page using #invoke. If you are running the tests through the debug console, use the code <code>require('Module:MyModule/tests').run()</code>. If you are running them from a wiki page, use the code <code><nowiki>{{#invoke:MyModule/tests|run}}</nowiki></code>. This will generate a table containing the results. It is also possible to display a more compact table by using the code <code><nowiki>{{#invoke:MyModule/tests|run|displayMode=short}}</nowiki></code>.
To run a testing module using the debug console, execute the following code: <code>require('Module:MyModule/testcases').run()</code>


== Tests ==
To run a testing module using wikicode, use <code><nowiki>{{#invoke:MyModule/testcases|run}}</nowiki></code>. This will generate a table containing the results. To display a summary of the results, rather than the entire table, use <code><nowiki>{{#invoke:MyModule/testcases|run|displayMode=short}}</nowiki></code>.


=== Error messages ===
==Assertion methods==
===Error messages===
The last parameter of all the assertion methods is a message that is displayed if validation fails.


The last parameter of all the test methods is an message that is displayed if validation fails.
<syntaxhighlight lang="lua">
 
<source lang="lua">
self:assertEquals('expected value', myModule.someCall(123), 'This tests whether the function x does y.')
self:assertEquals('expected value', myModule.someCall(123), 'This tests whether the function x does y.')
</source>
</syntaxhighlight>


=== assertTrue, assertFalse ===
===assertTrue, assertFalse===


<source lang="lua">
<syntaxhighlight lang="lua">
self:assertTrue(actual, message)
self:assertTrue(actual, message)
self:assertFalse(actual, message)
self:assertFalse(actual, message)
</source>
</syntaxhighlight>


These test whether the assertion evaluates to <code>true</code> or <code>false</code>. Note that in Lua <code>false</code> and <code>nil</code> evaluate to <code>false</code>, and everything else evaluates to <code>true</code>.
These methods assert that a value is true or false respectively. Note that in Lua, only the values false and nil evaluate to false; everything else evaluates to true, including the number 0 and the empty string.


<source lang="lua">
<syntaxhighlight lang="lua">
self:assertTrue(2 + 2 == 4)
self:assertTrue(2 + 2 == 4) -- true
self:assertTrue('foo')
self:assertTrue('foo') -- true
self:assertFalse(2 + 2 == 5)
self:assertTrue(0) -- true
self:assertFalse(nil)
self:assertFalse(2 + 2 == 5) -- true
</source>
self:assertFalse(nil) -- true
</syntaxhighlight>


=== assertStringContains ===
===assertStringContains===


<source lang="lua">
<syntaxhighlight lang="lua">
self:assertStringContains(pattern, s, plain, message)
self:assertStringContains(pattern, s, plain, message)
</source>
</syntaxhighlight>


This tests whether <code>pattern</code> is found in the string <code>s</code>. If <code>plain</code> is true, then <code>pattern</code> is interpreted as literal text; otherwise, <code>pattern</code> is interpreted as a [[mw:Extension:Scribunto/Lua reference manual#Ustring patterns|ustring pattern]].
This method asserts that <code>pattern</code> is found in the string <code>s</code>. If <code>plain</code> is true, then <code>pattern</code> is interpreted as literal text; otherwise, <code>pattern</code> is interpreted as a [[mw:Extension:Scribunto/Lua reference manual#Ustring patterns|ustring pattern]].


If the string is not found, the error message shows the values of <code>pattern</code> and <code>s</code>; if <code>s</code> is more than 70 characters long then a truncated version is displayed. This method is useful for testing specific behaviours in complex wikitext.
If the pattern is not found, the error message shows the values of <code>pattern</code> and <code>s</code>. (The output for these values is truncated if longer than 70 characters.) This method is useful for testing specific behaviors in complex wikitext.


<source lang="lua">
<syntaxhighlight lang="lua">
self:assertStringContains("foo", "foobar") -- passes
self:assertStringContains("foo", "foobar") -- true
self:assertStringContains("foo", "fobar") -- fails
self:assertStringContains("foo", "fobar") -- false
self:assertStringContains(".oo", "foobar") -- passes: matches "foo"
self:assertStringContains(".oo", "foobar") -- true: matches "foo"
self:assertStringContains(".oo", "foobar", true) -- fails: . is interpreted as a literal character
self:assertStringContains(".oo", "foobar", true) -- false: . is interpreted as a literal character
</source>
</syntaxhighlight>


=== assertNotStringContains ===
===assertNotStringContains===


<source lang="lua">
<syntaxhighlight lang="lua">
self:assertNotStringContains(pattern, s, plain, message)
self:assertNotStringContains(pattern, s, plain, message)
</source>
</syntaxhighlight>


This is the opposite of <code>assertStringContains</code>. The test will fail if <code>pattern</code> is found in the string <code>s</code>. If <code>plain</code> is true, then <code>pattern</code> is interpreted as literal text; otherwise, <code>pattern</code> is interpreted as a [[mw:Extension:Scribunto/Lua reference manual#Ustring patterns|ustring pattern]].
This method is the inverse of <code>assertStringContains</code>. It asserts that <code>pattern</code> is ''not'' found in the string <code>s</code>. If <code>plain</code> is true, then <code>pattern</code> is interpreted as literal text; otherwise, <code>pattern</code> is interpreted as a [[mw:Extension:Scribunto/Lua reference manual#Ustring patterns|ustring pattern]].


<source lang="lua">
<syntaxhighlight lang="lua">
self:assertNotStringContains("foo", "foobar") -- fails
self:assertNotStringContains("foo", "foobar") -- false
self:assertNotStringContains("foo", "fobar") -- passes
self:assertNotStringContains("foo", "fobar") -- true
self:assertNotStringContains(".oo", "foobar") -- fails: matches "foo"
self:assertNotStringContains(".oo", "foobar") -- false: matches "foo"
self:assertNotStringContains(".oo", "foobar", true) -- passes: . is interpreted as a literal character
self:assertNotStringContains(".oo", "foobar", true) -- true: . is interpreted as a literal character
</source>
</syntaxhighlight>


=== assertEquals ===
===assertEquals===


<source lang="lua">
<syntaxhighlight lang="lua">
self:assertEquals(expected, actual, message)
self:assertEquals(expected, actual, message)
</source>
</syntaxhighlight>


This tests whether the first parameter is equal to the second parameter. If both parameters are numbers, the values are instead compared using {{code|assertWithinDelta}} with delta 1e-8 (0.00000001) since numbers are represented as [[floating point]]s with limited precision.
This method asserts that the first argument is equal to the second argument. If both arguments are numbers, the values are instead compared using {{code|assertWithinDelta}} with delta 1e-8 (0.00000001). (See [[#assertWithinDelta]].)


<source lang="lua">
<syntaxhighlight lang="lua">
self:assertEquals(4, calculator.add(2, 2))
self:assertEquals(4, 2 + 2) -- true
</source>
</syntaxhighlight>


=== assertWithinDelta ===
===assertWithinDelta===


<source lang="lua">
<syntaxhighlight lang="lua">
self:assertWithinDelta(expected, actual, delta, message)
self:assertWithinDelta(expected, actual, delta, message)
</source>
</syntaxhighlight>


For two numbers, this tests whether the first is within a given distance (delta) from the second. This is useful to compare [[floating point]] numbers, which are used to represent numbers in the standard installation of Lua. (To be precise, it uses [[double-precision floating point]] numbers.) For example, on the version of Scribunto installed on the English Wikipedia, the expression <code>0.3 – 0.2 == 0.1</code> evaluates to <code>false</code>. This is because in practice, the expression <code>0.3 – 0.2</code> equals <code>0.09999999999999997780…</code> and the number <code>0.1</code> equals <code>0.10000000000000000555…</code>. The slight error between the two means that Lua does not consider them equal. Therefore, to test for equality between two floating point numbers, we should accept values within a small distance (delta) of each other, not just equal values. Note that this problem does not affect integers, which can be represented exactly using double-precision floating point numbers up to values of 2^53.
This method asserts that the first number argument is within a given distance (delta) from the second number argument. This is useful to compare [[wikipedia:Floating point|floating point]] numbers, which are used to represent numbers in the standard installation of Lua. (To be precise, it uses [[wikipedia:Double-precision floating point|double-precision floating point]] numbers.) For example, with the version of Scribunto installed on [[Path of Exile Wiki]], the expression <code>0.3 – 0.2 == 0.1</code> evaluates to false. This is because the expression <code>0.3 – 0.2</code> actually evaluates to 0.09999999999999997780… in practice. The slight difference between the two means that Lua does not consider them equal when compared using the equality operator (<code>==</code>). Therefore, to test for equality between two floating point numbers, we should accept values within a small distance (delta) of each other, not just equal values. Note that this problem does not affect integers, which can be represented exactly using double-precision floating point numbers up to values of 2^53.


<source lang="lua">
<syntaxhighlight lang="lua">
self:assertWithinDelta(0.1, calculator.subtract(0.3, 0.2), 1e-10)
self:assertWithinDelta(0.1, 0.3 - 0.2, 1e-10) -- true
</source>
</syntaxhighlight>


=== assertDeepEquals ===
===assertDeepEquals===


<source lang="lua">
<syntaxhighlight lang="lua">
self:assertDeepEquals(expected, actual, message)
self:assertDeepEquals(expected, actual, message)
</source>
</syntaxhighlight>


This tests whether the first parameter is equal to the second parameter. If the parameters are tables, they are compared recursively, and their [[mw:Extension:Scribunto/Lua reference manual#Metatables|__eq metamethods]] are respected.
This method asserts that the first argument is equal to the second argument. If the parameters are tables, they are compared recursively, and their [[mw:Extension:Scribunto/Lua reference manual#Metatables|__eq metamethods]] are respected.


<source lang="lua">
<syntaxhighlight lang="lua">
self:assertDeepEquals(table1, table2)
self:assertDeepEquals(table1, table2)
</source>
</syntaxhighlight>


=== assertTemplateEquals ===
===assertTemplateEquals===


<source lang="lua">
<syntaxhighlight lang="lua">
self:assertTemplateEquals(expected, template, args, message)
self:assertTemplateEquals(expected, template, args, message)
</source>
</syntaxhighlight>


This tests whether the first parameter equals a template call. The second parameter is the template name, and the third parameter is a table of the template arguments.
This method asserts that the first argument equals the result of expanding a template. The second argument is the name of the template, and the third parameter is a table of the parameters given to the template.


<source lang="lua">
<syntaxhighlight lang="lua">
self:assertTemplateEquals(4, 'add', {2, 2}) -- true if {{add|2|2}} equals 4
self:assertTemplateEquals(4, 'add', {2, 2}) -- true, assuming {{add|2|2}} equals 4
</source>
</syntaxhighlight>


Note that some tags written in XML notation cannot be tested correctly; see the note for the <code>assertResultEquals</code> function below.
Note that some special tags written in XML notation, such as <code><nowiki><pre></nowiki></code>, <code><nowiki><nowiki></nowiki></code>, <code><nowiki><gallery></nowiki></code> and <code><nowiki><ref></nowiki></code> cannot be compared correctly. These tags are converted to [[wikipedia:Help:Strip markers|strip markers]] before they are processed by Lua. Strip markers are unique, even when generated from identical input, so any tests testing these tags for equality will fail. This also applies to the <code>assertResultEquals</code> and <code>assertSameResult</code> methods.


=== assertResultEquals ===
===assertResultEquals===


<source lang="lua">
<syntaxhighlight lang="lua">
self:assertResultEquals(expected, text, message)
self:assertResultEquals(expected, text, message)
</source>
</syntaxhighlight>


This tests whether the first parameter equals the expansion of any wikitext. The second parameter can be any wikitext.
This method asserts that the first parameter equals the expansion of a string of wikitext. The second parameter can be any wikitext.


<source lang="lua">
<syntaxhighlight lang="lua">
self:assertResultEquals(4, '{{#invoke:Calculator|add|2|2}}')
self:assertResultEquals(4, '{{#invoke:Calculator|add|2|2}}') -- true, assuming {{#invoke:Calculator|add|2|2}} equals 4
</source>
</syntaxhighlight>


Note that some special tags written in XML notation, such as <code><nowiki><pre></nowiki></code>, <code><nowiki><nowiki></nowiki></code>, <code><nowiki><gallery></nowiki></code> and <code><nowiki><ref></nowiki></code> cannot be compared correctly. These tags are converted to [[Help:Strip markers|strip markers]] before they are processed by Lua. Strip markers are unique, even when generated from identical input, so any tests testing these tags for equality will fail. This also applies to the <code>assertTemplateEquals</code> and <code>assertSameResult</code> functions.
Note that some tags written in XML notation do not evaluate correctly using this method. (See [[#assertTemplateEquals]].)


=== assertSameResult ===
===assertSameResult===


<source lang="lua">
<syntaxhighlight lang="lua">
self:assertSameResult(text1, text2, message)
self:assertSameResult(text1, text2, message)
</source>
</syntaxhighlight>
 
This method asserts that the expansion of a given string of wikitext equals the expansion of another string of wikitext. This can be useful for verifying that a module behaves in the same way as a template it is intended to replace.


This tests whether the expansion of a given string of wikitext equals the expansion of another string of wikitext. This can be useful for verifying that a module behaves in the same way as a template it is intended to replace.
<syntaxhighlight lang="lua">
self:assertSameResult('{{add|2|2}}', '{{#invoke:Calculator|add|2|2}}') -- true, assuming {{add|2|2}} equals {{#invoke:Calculator|add|2|2}}
</syntaxhighlight>


<source lang="lua">
Note that some tags written in XML notation do not evaluate correctly using this method. (See [[#assertTemplateEquals]].)
self:assertSameResult('{{add|2|2}}', '{{#invoke:Calculator|add|2|2}}')
</source>


Note that some tags written in XML notation cannot be tested correctly; see the note for the <code>assertResultEquals</code> function above.
{{Adapted from Wikipedia|Module:ScribuntoUnit}}


== See also ==
{{Documentation categories|
* [[Module:UnitTests]]
<!-- Categories and interwikis go here. -->
[[Category:Documentation modules]]
}}

Latest revision as of 18:41, 4 January 2024

This subpage provides documentation for Module:ScribuntoUnit.

Lua logo

This module depends on the following other modules:

This module provides unit tests for other Scribunto modules. To test a module, you must create a separate testing module, usually located on the module's /testcases subpage. The testing module uses ScribuntoUnit to verify that the operations defined in it produce the expected results.

Test module structure

To make a test module (test suite), start with the following code:

local myModule = require('Module:MyModule') -- the module to be tested
local ScribuntoUnit = require('Module:ScribuntoUnit')
local suite = ScribuntoUnit:new()

After you have done this you can add individual test functions. Any member function of the suite object that has a name beginning with "test" is treated as a test by ScribuntoUnit.

function suite:testSomeCall()
    self:assertEquals('expected value', myModule.someCall(123))
    self:assertEquals('other expected value', myModule.someCall(456))
end

function suite:testSomeOtherCall()
    self:assertEquals('expected value', myModule.someOtherCall(123))
    self:assertEquals('other expected value', myModule.someOtherCall(456))
end

The tests you write should make assertions, and ScribuntoUnit will check whether those assertions are true. For example, assertEquals checks that both of the arguments it is given are equal. If ScribuntoUnit doesn't find an assertion to be true, then the test will fail and an error message will be generated. The error message will show which assertion failed verification. (Other checks on the assertions are not made at this time.)

The return value of the test module should be the suite object.

return suite

Running the tests

When implemented correctly with ScribuntoUnit, the testing module located on a module's /testcases subpage will run automatically and display the results.

To run a testing module using the debug console, execute the following code: require('Module:MyModule/testcases').run()

To run a testing module using wikicode, use {{#invoke:MyModule/testcases|run}}. This will generate a table containing the results. To display a summary of the results, rather than the entire table, use {{#invoke:MyModule/testcases|run|displayMode=short}}.

Assertion methods

Error messages

The last parameter of all the assertion methods is a message that is displayed if validation fails.

self:assertEquals('expected value', myModule.someCall(123), 'This tests whether the function x does y.')

assertTrue, assertFalse

self:assertTrue(actual, message)
self:assertFalse(actual, message)

These methods assert that a value is true or false respectively. Note that in Lua, only the values false and nil evaluate to false; everything else evaluates to true, including the number 0 and the empty string.

self:assertTrue(2 + 2 == 4) -- true
self:assertTrue('foo') -- true
self:assertTrue(0) -- true
self:assertFalse(2 + 2 == 5) -- true
self:assertFalse(nil) -- true

assertStringContains

self:assertStringContains(pattern, s, plain, message)

This method asserts that pattern is found in the string s. If plain is true, then pattern is interpreted as literal text; otherwise, pattern is interpreted as a ustring pattern.

If the pattern is not found, the error message shows the values of pattern and s. (The output for these values is truncated if longer than 70 characters.) This method is useful for testing specific behaviors in complex wikitext.

self:assertStringContains("foo", "foobar") -- true
self:assertStringContains("foo", "fobar") -- false
self:assertStringContains(".oo", "foobar") -- true: matches "foo"
self:assertStringContains(".oo", "foobar", true) -- false: . is interpreted as a literal character

assertNotStringContains

self:assertNotStringContains(pattern, s, plain, message)

This method is the inverse of assertStringContains. It asserts that pattern is not found in the string s. If plain is true, then pattern is interpreted as literal text; otherwise, pattern is interpreted as a ustring pattern.

self:assertNotStringContains("foo", "foobar") -- false
self:assertNotStringContains("foo", "fobar") -- true
self:assertNotStringContains(".oo", "foobar") -- false: matches "foo"
self:assertNotStringContains(".oo", "foobar", true) -- true: . is interpreted as a literal character

assertEquals

self:assertEquals(expected, actual, message)

This method asserts that the first argument is equal to the second argument. If both arguments are numbers, the values are instead compared using assertWithinDelta with delta 1e-8 (0.00000001). (See #assertWithinDelta.)

self:assertEquals(4, 2 + 2) -- true

assertWithinDelta

self:assertWithinDelta(expected, actual, delta, message)

This method asserts that the first number argument is within a given distance (delta) from the second number argument. This is useful to compare floating point numbers, which are used to represent numbers in the standard installation of Lua. (To be precise, it uses double-precision floating point numbers.) For example, with the version of Scribunto installed on Path of Exile Wiki, the expression 0.3 – 0.2 == 0.1 evaluates to false. This is because the expression 0.3 – 0.2 actually evaluates to 0.09999999999999997780… in practice. The slight difference between the two means that Lua does not consider them equal when compared using the equality operator (==). Therefore, to test for equality between two floating point numbers, we should accept values within a small distance (delta) of each other, not just equal values. Note that this problem does not affect integers, which can be represented exactly using double-precision floating point numbers up to values of 2^53.

self:assertWithinDelta(0.1, 0.3 - 0.2, 1e-10) -- true

assertDeepEquals

self:assertDeepEquals(expected, actual, message)

This method asserts that the first argument is equal to the second argument. If the parameters are tables, they are compared recursively, and their __eq metamethods are respected.

self:assertDeepEquals(table1, table2)

assertTemplateEquals

self:assertTemplateEquals(expected, template, args, message)

This method asserts that the first argument equals the result of expanding a template. The second argument is the name of the template, and the third parameter is a table of the parameters given to the template.

self:assertTemplateEquals(4, 'add', {2, 2}) -- true, assuming {{add|2|2}} equals 4

Note that some special tags written in XML notation, such as <pre>, <nowiki>, <gallery> and <ref> cannot be compared correctly. These tags are converted to strip markers before they are processed by Lua. Strip markers are unique, even when generated from identical input, so any tests testing these tags for equality will fail. This also applies to the assertResultEquals and assertSameResult methods.

assertResultEquals

self:assertResultEquals(expected, text, message)

This method asserts that the first parameter equals the expansion of a string of wikitext. The second parameter can be any wikitext.

self:assertResultEquals(4, '{{#invoke:Calculator|add|2|2}}') -- true, assuming {{#invoke:Calculator|add|2|2}} equals 4

Note that some tags written in XML notation do not evaluate correctly using this method. (See #assertTemplateEquals.)

assertSameResult

self:assertSameResult(text1, text2, message)

This method asserts that the expansion of a given string of wikitext equals the expansion of another string of wikitext. This can be useful for verifying that a module behaves in the same way as a template it is intended to replace.

self:assertSameResult('{{add|2|2}}', '{{#invoke:Calculator|add|2|2}}') -- true, assuming {{add|2|2}} equals {{#invoke:Calculator|add|2|2}}

Note that some tags written in XML notation do not evaluate correctly using this method. (See #assertTemplateEquals.)

This module was adapted from Module:ScribuntoUnit on Wikipedia.
Adaptation is noted for reference and attribution only. This module may differ from the original in function or in usage.