テスト関数の作り方
テストが大きくなってくると、
まずは、
sub check_numeric_array {
is $_[0], array {
all_items match qr/^[0-9]+$/;
etc;
}, 'すべての要素が数値である'; ――(1)
}
check_numeric_array([0, '1234']);
check_numeric_array(['a']); ――(2)
この場合に問題となるのが、
$ perl test-func.t
# Seeded srand with seed '20180625' from local date.
ok 1 - すべての要素が数値である
not ok 2 - すべての要素が数値である
# Failed test 'すべての要素が数値である'
# at test-func.t line 5.
# +------+--------------+----+---------------+------+
# | PATH | GOT | OP | CHECK | LNs |
# +------+--------------+----+---------------+------+
# | | ARRAY(省略)| | <ARRAY> | 2, 5 |
# | [1] | a | =~ | (?^:^[0-9]+$) | 3 |
# +------+--------------+----+---------------+------+
この問題を解決するためには、is
やok
などのテスト関数の1つ上の呼び出し元が反映されるように伝える必要があります。Test::Builder
の場合は$Test::Builder::Level
というグローバル変数によって管理する必要がありましたが、context
関数を呼び出すことでコンテキストを作り、release
メソッドを呼び出します。こうすることで、
sub check_numeric_array {
my $ctx = context;
is $_[0], array {
all_items match qr/^[0-9]+$/;
etc;
}, 'すべての要素が数値である';
$ctx->release;
}
テスト関数のテスト
テスト関数を書いたなら、
イベント名 | アクセサ | 説明 |
---|---|---|
Ok | pass、 | okやis関数によるテストの結果が成功した場合はpassが1となり、 |
Diag | message | diag関数によってメッセージが出力された |
Note | message | note関数によってメッセージが出力された |
Skip | reason | skip関数によりテストがスキップされた |
Subtest | pass、 | subtest関数によりsubtest化されたテスト、 |
イベントの取り出し
イベントの取り出しには、intercept
関数を使います。コードブロック内で実行されたテストは実際には結果としては出力されず、event
ビルダを使いチェックします。
次のコードでは、
use Test2::Util::Table qw/table/;
is intercept {
is [1, 2], [0]; ――(1)
}, array {
event Ok => { pass => 0 }; ――(2)
event Diag => {
message => match qr{^\n?Failed test},
};
event Diag => {
message => join "\n", table( ┓
header => [qw/PATH GOT OP CHECK/], |
rows => [ |
['[0]', '1', 'eq', '0'], |
['[1]', '2', '!exists', |
'<DOES NOT EXIST>'], |(3)
], |
), |
}; |
end; |
}; ┛
event
ビルダにより、Ok
イベントが発行されていてその結果が失敗していることをチェックしています。
Test2::Util::Table
にあるテーブルを作るヘルパを利用しています。
なお、Test2::Tools::EventDumper
を使うことで、
テストモジュールの一例
ここでテストモジュールの一例として、Test2::Tools::JSON
というモジュールを紹介します。このモジュールは、Test::Deep::JSON
をTest2用に書きなおしたものです。
使い方は、Test2::Tools::JSON
がエクスポートするjson
関数を使うことで、
use Test2::Tools::JSON;
is {
foo => 'bar',
payload => '{"a":1}',
}, {
foo => 'bar',
payload => json({a => E}),
};
上記のテスト中のJSONを{"a":2}
と書き換えて失敗させてみます。図2のように、
# +-----------------------+---------+------+-------------+-----+ # | PATH | GOT | OP | CHECK | LNs | # +-----------------------+---------+------+-------------+-----+ # | {payload} | {"a":1} | JSON | HASH(省略)| 4 | # | {payload} <JSON>->{a} | 1 | eq | 2 | | # +-----------------------+---------+------+-------------+-----+
まとめ
本稿では、Test::Builder
の問題を解決し、Test2::V0
といった高機能なテストモジュールが使え、
本稿で紹介したものは一部にすぎません。RSpecライクなテスト記法を提供するTest2::Workflow
や、prove
を置き換える形のテストランナーであるyath
など、
さて、