失敗のテストのテストの話
何を言っているのか良く分からないかもしれませんが、そういう話。
拙作のTest::Module::Usedとか、もっとメジャーどころだと Test::Pod とか Test::Perl::Critic とか、自前で ok() 相当のメソッドや関数を持っているモジュールがあります。こういうモジュールでは、成功する場合は普通にテストを書けばよいですが、失敗する場合のテストとして、
ok( !someting_ok(), "failure is expected");
みたいな感じのテストは出来ません。テストが失敗すると、本当に失敗しちゃってテストが通らないから。
多分解決策は 2 つあって、
- パブリックなインターフェースではなく、内部構造をうまく使ってテストする(テスト自体を失敗させない)
- Test::Builder::Testerを使う
のどちらか、になるかと思います。で、Test::Module::Used の今回のリリース(0.2.1_04)では、後者を使ってテストを書いてみたのだけど、うーん、すごく気持ち悪い。
t/014_requires_ok_fail.t at master from tsucchi's Test-Module-Used - GitHub
#...(最初は省略) test_out("1..4"); test_out("ok 1 - check required module: Module::Used"); test_out("not ok 2 - check required module: Plack"); test_out("ok 3 - check required module: Test::Module::Used"); test_out("ok 4 - check required module: Test::Class"); $used->requires_ok(); my $builder = Test::Builder->new(); $builder->reset;# reset because plan is automatically set in Test::Module::Used. plan tests=>1; test_test(skip_err=>1);
「なんだよ、その builder->reset」とか、「skip_err していいのかい?」とか、いろいろ突っ込みどころはあるのですが、頑張ったけどコレよりうまく書ける気がしません。
plan を自前でセットしている場合、多分 reset するしかないっぽいです。あとはコンストラクタで、plan をセットしないオプションを提供するとか。でも、このモジュールは無駄にオプション多いから、もう増やしたくないし。
err も最初は頑張ってテストしようとしてみたのですが、すごくセンシティブで、全然うまくいかないので、あきらめました。
Test::Builder::Tester はちょっと厳格すぎるところがあるので、もうちょいカジュアルに、「このエラーメッセージが含まれていたらOK」くらいな感じでテストできるといいのになぁ、とか思いました。