モジュール:ScribuntoUnit/doc
このモジュールは、他のLuaモジュールのためのユニットテストを提供します。モジュールをテストする際には、通常、Module:Module name/testcases
の場所にテスト用の専用モジュールを作成します。テストはScribuntoUnitモジュールによって行われ、テストモジュールで定義された動作が期待通りの結果を出力するかを検証します。
テストモジュールの構造
編集テストモジュール(テストスイート)を作成するには、次のコードから始めます。
local myModule = require('Module:MyModule') -- テストするモジュール
local ScribuntoUnit = require('Module:ScribuntoUnit')
local suite = ScribuntoUnit:new()
これを行った後、各テスト関数をsuite
オブジェクトに追加することができます。test
で始まる関数はテストとして認識されます。(一方、その他の関数は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
作成するテストにはアサーションの設定が必要で、ScribuntoUnitはそのアサーションが真かどうかを検証します。例えば、assertEquals
は与えられた二つの引数が等しいかを確認します。ScribuntoUnitがアサーションを真と判断できない場合、テストは失敗となり、エラーメッセージが表示されます。このエラーメッセージは、問題のあるアサーションを示すものです。(その時点では、他のアサーションの検証は行われません)
テストモジュールを完了するには、suite
オブジェクトを返す必要があります。
return suite
テストの実行
編集テストは2つの方法で実行できます。一つ目はLuaデバッグコンソールを使用する方法、もう一つは#invokeを利用してWikiページから実行する方法です。デバッグコンソールでの実行には、require('Module:MyModule/testcases').run()
というコードを使います。一方、Wikiページからの実行では、{{#invoke:MyModule/testcases|run}}
を使用します。これにより、結果を示す表が表示されます。もし結果をよりコンパクトな形式で表示したい場合は、{{#invoke:MyModule/testcases|run displayMode=short}}
を利用します。
テスト
編集エラーメッセージ
編集全てのテストメソッドにおいて、最後のパラメータは検証失敗時に表示されるメッセージとなります。
self:assertEquals("expected value", myModule.someCall(123), "The call to myModule.someCall(123) didn't return the expected value.")
fail
編集self:fail(message)
無条件に検証に失敗します。
self:fail("Test failed because of X.")
assertTrue, assertFalse
編集self:assertTrue(expression, message)
self:assertFalse(expression, message)
これらは、指定された式がtrue
かfalse
に評価されるかを検証します。Luaでは、false
とnil
だけがfalse
として評価され、それ以外の値は全てtrue
として評価されることに注意してください。
self:assertTrue(2 + 2 == 4)
self:assertTrue('foo')
self:assertFalse(2 + 2 == 5)
self:assertFalse(nil)
assertStringContains
編集self:assertStringContains(pattern, s, plain, message)
これは、文字列s
内にpattern
が存在するかどうかを検証します。plain
がtrueである場合、pattern
はリテラルテキストとして扱われます。そうでない場合は、pattern
はustring パターンとして解釈されます。
self:assertStringContains("foo", "foobar") -- passes
self:assertStringContains("foo", "fobar") -- fails
self:assertStringContains(".oo", "foobar") -- passes: matches "foo"
self:assertStringContains(".oo", "foobar", true) -- fails: . is interpreted as a literal character
assertNotStringContains
編集self:assertNotStringContains(pattern, s, plain, message)
これはassertStringContains
の逆の動作をします。文字列s
内にpattern
が存在する場合、検証は失敗となります。plain
がtrueである場合、pattern
はリテラルテキストとして扱われます。そうでない場合は、pattern
はustring パターンとして解釈されます。
self:assertNotStringContains("foo", "foobar") -- fails
self:assertNotStringContains("foo", "fobar") -- passes
self:assertNotStringContains(".oo", "foobar") -- fails: matches "foo"
self:assertNotStringContains(".oo", "foobar", true) -- passes: . is interpreted as a literal character
assertEquals
編集self:assertEquals(expected, actual, message)
これは、最初のパラメータと2番目のパラメータが等しいかどうかを検証します。両方のパラメータが数値である場合、数値は限られた精度で浮動小数点数として表されるため、assertWithinDelta
を使用して、デルタとして1e-8(0.00000001)を指定し、値を比較します。
self:assertEquals(4, calculator.add(2, 2))
assertNotEquals
編集self:assertNotEquals(expected, actual, message)
これは、最初のパラメータが2番目のパラメータと等しくないかどうかをテストします。両方のパラメータが数値である場合、数値は限られた精度で浮動小数点数として表されるため、assertWithinDelta
を使用して、デルタとして1e-8(0.00000001)を指定し、値を比較します。
self:assertNotEquals(5, calculator.add(2, 2))
assertWithinDelta
編集self:assertWithinDelta(expected, actual, delta, message)
2つの数値を比較する際、最初の数値が2番目の数値から指定した距離(デルタ)以内にあるかどうかを検証します。これは、Luaで数値を倍精度浮動小数点数として表現する際の誤差を考慮してのことです。例えば、英語版ウィキペディアのScribtoでは、式0.3-0.2==0.1
はfalse
と評価されるのは、0.3-0.2
が実際には0.09999999999999997780…
、0.1
が0.10000000000000000555…
と評価されるためです。この微小な誤差のため、2つの浮動小数点数を比較する際には、完全に一致するだけでなく、一定のデルタ内で近いかどうかを基準にする必要があります。なお、この問題は整数には適用されません。整数は、2^53の値までの倍精度浮動小数点数を使用して正確に表すことができます。
self:assertWithinDelta(0.1, calculator.subtract(0.3, 0.2), 1e-10)
assertNotWithinDelta
編集self:assertNotWithinDelta(expected, actual, delta, message)
2つの数値について、最初の数値が2番目の数値から指定された距離内に位置していないかを検証します。このテストは、assertWithinDeltaの反対の動作をします。
self:assertNotWithinDelta(0.1, calculator.subtract(0.3, 0.1), 1e-10)
assertDeepEquals
編集self:assertDeepEquals(expected, actual, message)
最初のパラメータと2番目のパラメータが等しいかどうかを検証します。パラメータがテーブルである場合、再帰的に比較が行われ、その際に__eq メタメソッドが考慮されます。
self:assertDeepEquals(table1, table2)
assertTemplateEquals
編集self:assertTemplateEquals(expected, template, args, message)
この検証は、最初のパラメータがテンプレート呼び出しと一致するかどうかを確認します。2番目のパラメータはテンプレートの名前を指定し、3番目のパラメータはテンプレートの引数をテーブル形式で指定します。
self:assertTemplateEquals(4, 'add', {2, 2}) -- true if {{add|2|2}} equals 4
XML表記で書かれたタグの中には、正しく検証できないものがあることに注意してください。以下のassertResultEquals
関数の注意を参照してください。
assertResultEquals
編集self:assertResultEquals(expected, text, message)
これは、最初のパラメータが特定のウィキテキストの展開結果と一致するかどうかを検証します。2番目のパラメータには任意のウィキテキストを指定できます。
self:assertResultEquals(4, '{{#invoke:Calculator|add|2|2}}')
<pre>
、<nowiki>
、<gallery>
、<ref>
などのXML形式で記述される特定のタグは、正しく比較するのが難しい点に注意してください。これらのタグは、Luaで処理される前にストリップマーカーに変換されるためです。ストリップマーカーは、同じ入力からでも一意の値が生成されるので、これらのタグの等価性を検証するテストは失敗します。この特性は、assertTemplateEquals
関数とassertSameResult
関数にも影響します。
assertSameResult
編集self:assertSameResult(text1, text2, message)
これは、指定されたwikitextの文字列が展開された結果が、別のwikitextの展開結果と一致するかどうかを検証します。これは、モジュールが置き換える予定のテンプレートが期待通りに動作しているかを確認する際に役立ちます
self:assertSameResult('{{add|2|2}}', '{{#invoke:Calculator|add|2|2}}')
XML表記で書かれたタグの中には、正しく検証できないものがあることに注意してください。上記のassertResultEquals
関数の注意点を参照してください。
assertThrows
編集self:assertThrows(fn, expectedMessage, message)
これは、指定された関数が例外を投げるかどうかを検証します。expectedMessage
がnil
でない場合、そのエラーメッセージが例外として投げられたかどうかもチェックされます。
関連項目
編集