taro-nishinoの日記: no_planはずるい?
最近のCPANでは、テストスクリプトにテスト数を宣言しない流儀が定着して来ましたが、それをAdam Kennedy氏は″The unfortunate demise of the plan″で嘆いておられます。Test::Moreにdone_testingが追加されたことも、テスト数を宣言しないことに拍車を掛けたようですが、私個人はMatt S. Trout氏のエッセイ″A cunning no_plan?″を読んで、始めてdone_testingが追加されたことを知りました。テスト数を宣言しないことに両論があるのは知っていますが、私は宣言しない方に肩入れしたいと思います。理由は簡単です。要は数えるのも面倒くさいからです。
以下に″A cunning no_plan?″の私訳を載せておきます。なお、エッセイの最後部分には氏の著書に関する記述があるのですが、それは本題とは関係が無いと思いましたので省きました。
no_planはずるい?
2009年7月21日 Matt S. Trout
数えるテストプランは悪いし、間違っていて、実のところ何の役にも立たない理由
″The Definitive Guide To Catalyst″の編纂の過程で、私は共著者及びテクニカルレビューアーと道義的な議論を持った。彼等が指摘したことの一つは、私が怠惰な男だから、明らかに私の見落としで短いメソッド内に明示的なreturnステートメントを置いていないことだった。そして、そのコードは正された。しかし、テスティングプランについての討論はもっと面白かった。
非常に多くのperlテストが、Test::More又はその変形を使って書かれている。「通常」のアプローチ又は少なくとも教えられたことは、ファイルの先頭に以下の如く関心のあるテストの数を宣言することだ。
use Test::More tests => 23;
又は
use Test::More;
...
plan tests => 23;
しかし、本では、私は以下のように書いている。
use Test::More qw(no_plan);
それは、どんなテストが走るのであれ、いくつが実際に走ったのか最後にチェックしないことを意味する。私の「しかし」はレビューアーを痛く怒らせ、「貴方が最も簡単なコードを見せたいがために、こういうことをしており、製品ではしないことを希望する」のようなコメントを受けた。
はい、確かに、そのつもりです。
私はプランを数えることは何の得にもならず、いんちきテスト一式の要因となる得るうわべの怠惰を促進し、大きなチームにスケールしないことを主張する。つまりは、余りにも怠惰過ぎて自分で完全なアプリケーションを書けないので、私は大きなチームにスケールすることを多いに気遣っている。
ところで先ずは反対のケースから。何故、数えるテストプランがいいのか? 第一に、次のようなコードを貴方がテスト一式のどこかに書き、中途で走らないことを防ぐ。
exit 0;
いや、待て、何?! そんなことをしたコードを貴方が見た最後はいつだったのか? 確かに、私が時間を費やすのはperlアプリケーションを書くことだが、そんなことをする程簡単なものではない。過去数年私が使って来たライブラリで、そんなことをするのは一つも無いし、私が一緒に働いて来た未熟なデベロッパーで、そのようなアホなミスを何度もする者は一人もいない。
もっとはっきり言えば、私はテスト一式の終わりの方をカットしたいことさえあり、意図的にexitステートメントを加え、私のやりたことと同じ効果を持たせたことがあった。
第二に、数えるテストプランは、ループテストが正しいことをしなければ、それは捕らえられるだろう。つまりは、以下のような間違った要素数を返すgimme_a_list()が捕らえられる。
foreach my $member (gimme_a_list()) {
ok($member->is_shiny, 'Member '.$member->name.' is shiny');
}
まぁ、そう、何も返さないgimme_a_list()を捕まえるだろう。しかし、返される要素数を気にするなら、一体何故それをテストしないのか?! つまり私が言いたいのは、それが問題なら次のように書くべきである。
my @list = gimme_a_list();
cmp_ok(scalar(@list), '==', 3, 'gimme_a_list() returned three entries');
foreach my $member (@list) {
...
これは、必要な場所の近くで重要な情報を保持するのみならず、一つのループテストが多い回数や少ない回数を走る場合も捕捉する(いや、実はそうではない、私はこれを見たことがある...)。従って、私見では、その議論は筋も通らない。
おそらく私の観点から最も重要なことは、テストプランが引き起こすマージの競合である。つまりは、テストファイルが71テストから出発して、私が自分のブランチに3つのテストを追加し、他の誰かがそれに4つ加えるなら、私達はマージで競合を抱え、開発者マージは、それを正しい最終の値、78テストに直さなければならないだろう。今や完全に無意味なバージョン履歴の内に競合を抱えている。
更に悪いことには、私達両方が3つのテストを各々加えるならば、マージの競合は無いが、結果のテストファイルは最早失敗であろう。おめでとう、貴方はビルドを壊した。貴方と他の野郎のテストはどちらも絶対に正しいのだから、貴方は自分のしていたことを認識すらしなかった!
多くの場合no_planがいいことである理由について、貴方が少なくとも納得することを私は希望する。更に良いことに、今や「exit 0」問題に治療薬がある。Test::Simple(Test::Moreを含んでいる) 0.88又はそれ以上であれば、以下のように出来る。
use Test::More; # no_plan not required
...
done_testing;
そして、テストスクリプトが分岐点で逃げるならば、適切なエラーが得られるだろう。
no_planはずるい? More ログイン