PHPでTest::MoreするならLimeを使おう
「自分のメイン言語はPerlだけど、会社ではPHP使ってる。PHPでもTest::Moreみたいにテストしたい」という人は結構いるんじゃないかと思います。
「php test::more」でググると出てくるのはここ。
紹介されているtest-more.phpは確かにTest::Moreライクな実装ですが、機能的に不足があったり全体的に作りが古くて、自分で拡張するにも今ひとつ。
そんなあなたにsymfonyで採用されている独自のテストフレームワーク「Lime」。これがまさにPHP版Test::Moreです。
このLimeはsymfonyのテストフレームワークとしてもう2年程前から採用されているのですが、Test::Moreを基にしたという記述が無いためか、それっぽいキーワードでググっても全く引っかかって来ません。両方知ってて、そのことをあえて書く人もいなかったのかな。これは大きな損失だろうということで宣伝エントリです。
Limeは単一ファイルで構成されているので、リポジトリから引っ張ってきて require 'lime.php' してやればOK。
一つ一つ細かくは見ていないのですが、Tracのwikiを見る限りではまんまTest::Moreですね。
クラスとしてのみ提供されているので $t->method() の形で呼び出すところとか、
<?php $t = new lime_test( $amount, new lime_output_color() );
として出力用のクラスに lime_output_color を指定すると出力がカラーになるところとか、そういうところが特徴でしょうか。
ちょっと気になったのは、isで数値や文字列を比較するのに==を使っているところ。
<?php $t->is( 1, true, '1 == true' ); $t->is( 0, false, '0 == false' ); $t->is( 0, '', '0 == nullstring' );
あたりが通ってしまうので、知らないと思わぬ落とし穴にはまる可能性もあります。
代表的なところではstrposあたりでしょうか。strposは文字列が最初に現れる場所を見つけるPHPの標準関数ですが、見付からなかった場合はfalseを、最初の文字にマッチした場合は0を返します。この関数を使う時は、戻り値を===で判定しないと不具合の元になります(そもそもそんな実装ってどうなんだという話はさておき)。
===でしっかり比較したい時は、
<?php $t->ok( $a === true ); $t->ok( $b === false );
のようにテストコード側で明示的に書いてやる必要があるようです。
オリジナルのTest::Moreの挙動から極力離れないというポリシーだと思いますが、PHPでそこまで忠実にする必要があったのかは個人的にはちょっと疑問です。コードを見るとis_deeplyにスカラ値を投げてやると===で比較しているので、そちらを使うという手もありますが、本来の意味合いとは違うよなぁ…
それはさておき、symfonyで正式採用されているということで、いろんな意味で安心して使えるライブラリと言っていいでしょう。
このエントリが「php test::more」で検索してヒットするようになれば、自前でTest::More互換の物を作って、$t->〜の形だけでなくグローバルな関数としても使えるExporterを用意して、インデントも同じになるように調整して、実装を残していたis_deeplyやtodoをどういう形にしようか思いを馳せつつ参考資料は無いかと探していたら、たまたま見付けてよく見たらこれそのまんまTest::Moreじゃねぇか今まで俺が作っていた物は一体… なんて悲劇が起こらなくなるので大変いいと思います。
関連エントリ:limeにプラグイン機構を乗っけてみた - Lism.in * blog - nekoya (id:studio-m)