2006/10/25 (水)
■ Test::Base driven Development

404 Blog Not Found:テキストエディタさえあればできるTDD
まあいわんとすることはわかるのだが、例がわるくて Perl のほうがぜんぜん簡単に見えないし、TDD のポイントは Test を書いてインタフェースを決め、fail させ、実装コードを書いて pass させるという点にある(と思う)から、コード使いでない人がかける云々というのはポイントではないはずだ。
それにいくら Perl を贔屓目に見たところで、実際の実装コードとテストコードを違う言語で書くことにメリットはほとんどないはずだから、ここでも Java は見にくくて云々は関係ない。
ついでなので、Test::Base でテストを書くとこのようになる。Lingua::JA::Hepburn::Passport (入力されたひらがな・カタカナをヘボン式ローマ字に変換)を例にすると、
use strict;
use Test::Base;
use Encode;
use Lingua::JA::Hepburn::Passport;
sub hepburn {
Lingua::JA::Hepburn::Passport->new->romanize( decode_utf8($_[0]) );
}
filters {
input => [ 'chomp', 'hepburn' ],
expected => [ 'chomp' ],
};
run_is 'input' => 'expected';
__END__
===
--- input
なんば
--- expected
NAMBA
===
--- input
ほんま
--- expected
HOMMA
===
--- input
さんぺい
--- expected
SAMPEI
===
--- input
はっとり
--- expected
HATTORI
===
--- input
きっかわ
--- expected
KIKKAWA
===
--- input
ほっち
--- expected
HOTCHI
===
--- input
はっちょう
--- expected
HATCHO
===
--- input
こうの
--- expected
KONO
===
--- input
おおの
--- expected
ONO
===
--- input
ひゅうが
--- expected
HYUGA
===
--- input
ちゅうま
--- expected
CHUMA
===
--- input
おーの
--- expected
ONO
=== Katakana
--- input
チュウマ
--- expected
CHUMA
真ん中にある __END__ の上がテストコード、下がそれに食わせるデータである。いわゆる MVC とかでデザインとロジックの分離!とか言うが、テストにおけるテストコードとテストデータの分離、といってもいいかもしれない。
Test::More では .t にのっぺり書いていくのがいや、という人も Test::Base ならこのようにかけて安心。「結局__END__ 上のテストコード(フィルタとか)は .t ごとに書くんじゃねえの」という方は、t/MyTest.pm とか書いて .t からは use t::MyTest; と呼び出せば再利用できる。
というわけで自分が CPAN モジュールを書くときは、
- モジュール名決める
- pmsetup で雛形作成
- APIを決めて、POD を書く
- t/01_module.t にテストコードとテストデータを書く
- make test こける
- 実装
- make test OK
- コーナーケースのデータを .t に追加
というようなサイクルで実装してます。
コーナーケースの発見がたまに難しいわけだけど、それに注目しているのが LectroTest という仕組み。Haskell では QuickCheck, CPAN には Test::LectroTest とかあるが、ちょっと test spec の作り方が難しそう。うまいこと Test::Base にフィードするデータをこんな感じでつくれると回帰テストに役立ちそうだなんだけど。