(1)はこちら 、( 2)はこちら から。
Test::Stream──新しいテストフレームワーク
Test::Builder
はほぼすべてのテストモジュールのベースとなっているフレームワークですが、1つのモジュールにすべての機能(テスト数のカウントやテスト結果のフォーマットなど)が詰め込まれたモノシリック構造になっていることや、機能拡張用のAPIフックポイントが用意されていないことなど、拡張性はあまり考慮されていません。そのため、Test::Builder
自体の機能を拡張したい場合はそれぞれのテストモジュールがTest::Builder
のメソッドにパッチを当てていくしかありませんでした。
Test::Builder2の開発スタート、そして中止
このような状況を受けて、2008年ごろにTest::More
のメンテナーだったMichael G SchwernによってTest::Builder
を根本的に作りなおすTest::Builder2の開発がスタート しました。これはモノシリックな構造だったTest::Builderを全面的に書き換え、APIを整備し、拡張しやすい構造に作り替えるプロジェクトでしたが、結局正式にリリースされることはなく、長い開発期間を経て2014年に開発は中止されました。
Test::Streamの開発スタート
Test::Builder2
の開発中止が決まったタイミングでTest::More
のメンテナーを引き継いだChad Granumが開発を進めている新しいテストフレームワークがTest::Stream
です。
Test::Stream
の特徴は次のとおりです。
is
やlike
がリファレンスもテスト可能に
TAP出力のUTF-8サポート
プラグイン機構の導入
テスト結果のオブジェクト化
is
がリファレンスもテストできるようになったので、is
とis_deeply
を使い分ける必要がなくなりました。比較したいデータを渡せばTest::Stream
側でよしなに対象のデータ型を判断してくれます。また、TAPの出力でUTF-8がサポートされたので、Unicodeを含む文字列があっても、警告メッセージが出力されることはありません。
use Test::Stream -V1;
is( +{ lang => 'perl5' }, +{ lang => 'perl6' }, '違う言語?';
done_testing;
テストが失敗したときのメッセージもとてもわかりやすくなりました。先ほどのテストを実行すると次のように表示されます。
not ok 1 - 違う言語?
# Failed test '違う言語?'
# at stream.t line 2.
# +--------+-------+----+-------+
# | PATH | GOT | OP | CHECK |
# +--------+-------+----+-------+
# | {lang} | perl5 | eq | perl6 |
# +--------+-------+----+-------+
1..1
プラグイン機構の導入とともに、従来のTest::More
相当の機能はもちろんのこと、Test::Exception
、Test::Output
といったメジャーなテストモジュール相当の機能がプラグインとして提供されていますし、さらにはBDD(Behavior Driven Development 、振舞駆動開発)スタイルでテストを書くためのプラグインまで用意されています。
テストモジュールを作るうえでは、テスト結果が最初からオブジェクト化されているため、interceptという関数で簡単にテスト結果をテストできるようになりました(リスト5 ) 。
リスト5 test_stream.t
use Test::Stream -V1, -Tester;
my $results = intercept {
is(1, 1, 'success test');
is(1, 2, 'failure test');
};
is($results->[0]->name, "success test");
like(
$results->[1]->diag,
[qr/Failed test 'failure test'/],
);
done_testing;
Test::Stream
はCPANにアップされているのでcpanm Test::Stream
でインストールできます。執筆時点(2015年11月)では一部の機能は実験リリース扱いとなっていますが、今後のPerlのテスト環境を大きく改善する注目のプロジェクトです[3] 。
Perl 6のテスト
最後にPerl 6のテストについて少し紹介します。
2015年のPerl界隈の最大のニュースと言えば、Perl 6がついに正式リリースされると発表されたことです。執筆時点の最新テストリリースであるRakudo Star 2015.09 をベースに、Perl 6のテスト方法を紹介します[4] 。
Testモジュール
Perl 6にはそのものずばりTest
というテストモジュールが用意されていて、ほぼTest::More
とTest::Exception
相当のテスト関数が用意されています。テストのスタイルも従来のPerl(以降、区別するためにPerl 5と記載します)と同じです(リスト6 ) 。
リスト6 perl6-test.t
use v6;
use Test;
is("Perl6".chars, 5, "文字列の長さのテスト");
my $str = "Perl 6 will be available this Christmas";
like($str, rx:i/christmas/, "正規表現のテスト");
subtest {
# Perl 6のオブジェクト機構を使ってクラスを定義
class Person {
has Str $.name is rw;
has Int $.age is rw;
}
# オブジェクトの作成と、プロパティの設定
my $person = Person.new;
$person.name = "Larry";
$person.age = 61;
# プロパティのテスト
is( $person.name, 'Larry', 'name属性のテスト');
cmp-ok($person.age, &infix:«>=», 60, 'age属性のテスト');
}, 'オブジェクトのテスト';
throws-like(
sub { die "throw exception" },
X::AdHoc, # dieの送出する例外の型は、X::AdHoc
message => "throw exception",
"例外のテスト"
);
done-testing;
Perl 5のテストに慣れている人ならば、リスト6を見ただけでだいたい雰囲気はつかめると思いますが、それぞれの意味は次のとおりです。
(1) (2) のis
、like
は、Test::More
の同名のテスト関数と同じ
(3) のsubtest
は、引数の順番が変わった以外はTest::More
のsubtest
と同じ
(4) のcmp-ok
は、関数名が(Perl 6の命名付与規約に合わせて)変わったのと、比較演算子によって多少指定のしかたが変わった以外はTest::More
のcmp_ok
と同じ
(5) のthrows-like
は、Perl 6で導入された例外クラスをテストするテスト関数
(6) のdone-testing
は、Test::More
のdone_testing
と同じ
また、リスト6ではテスト名をすべて日本語で書いていますが、Perl 6では文字列のデフォルトのエンコ
ーディングがUTF-8になったので、そのまま出力しても警告メッセージは出力されません。
テストの実行と結果の確認
テストを実行すると結果がTAP形式で出力される点は、Perl 5と完全に同じです。
Perl 6のテストの実行結果
$ perl6 perl6-test.t
ok 1 - 文字列の長さのテスト
ok 2 - 正規表現のテスト
ok 1 - name属性のテスト
ok 2 - age属性のテスト
1..2
ok 3 - オブジェクトのテスト
1..3
ok 1 - code dies
ok 2 - right exception type (X::AdHoc)
ok 3 - .message matches throw exception
ok 4 - 例外のテスト
1..4
prove
コマンドは(現時点では)Perl 5のprove
コマンドをそのまま利用します。Perl 6のテストも拡張子は.t
を使用するので、Perl 5と区別するために--exec perl6
オプションを付けて実行します。
Perl 6におけるproveコマンドの実行
$ prove --exec perl6 perl6-test.t
perl6-test.t .. ok
All tests successful.
...
Result: PASS
Perl 6の仕様をテストするroast
Perl 5では「実装が仕様」だったので明確な仕様書は存在しませんでしたが、Perl 6には明確に仕様書が存在します 。
さらに、この仕様書どおりに実装されていることを確認するためのroastというテストセット も用意されています。このテストセットでも当然Test
モジュールが使われています。Perl 6を学習するためには、まずこのテストを一通り見ることをお勧めします。
まとめ
Perlのテストモジュールの使い方と作り方を一通り解説し、最後に少しだけPerl 6でのテスト方法を紹介しました。
Perlのテストは、Test::More、TAPの読み方、proveコマンドさえ覚えればすぐに始めることができます。足りない機能があればCPANモジュールを使ったり、Test::Builderで新しいテストモジュールを作ったりすることで対応できます。読者のみなさんも、今回の記事を参考に、ぜひどんどんテストを書いてみてください。Happy Perl Testing!
さて、次号の執筆者はpapixさんで、テーマは「Perlで作るInfrastructure as Code」です。