CPAN形式を用いた開発手法(コーディングからテストの流れ)
CPAN形式を用いた開発手法(コーディングからテスト)
CPANを一番最初に使い始めたのは数年前ブックマークサイトを作ったとき
HTML::ExtractContentがきっかけでそれ以降、色々なモジュールを試すようになった。
使用していて分かる通り、
CPAN形式というのは、通常のアプリケーションの開発にもとても機能的に動作する。
ソースなどはモダンPerl
メリット
1.開発〜テスト〜コミットの一連の流れが自然
2.形式の統一化。ーーレイアウトが統一されていることで共有しやすい
3.パッケージング方法がメンテナンス/開発されている
CPAN形式はPerlという言語そのものと結合している。また後方互換にも優れている。
4.依存関係の自動検知/解決方法が存在している
5.最終的に配布可能
レイアウト
Example-Software/ Makefile.PL/ t/ 00_compile.t lib/ Example/ Software.pm
ソース
#lib/Example/Software.pm package Example::Software; use strict; our $VERSION = '0.00001'; 1;
#Makefile.PL <- testを省略してもt/ディレクトリ直下の.t.ファイルをテストととしてみなす use strict; use inc::Module::install; name('Example-Software'); all_from('lib/Example/Software.pm'); #test('t/*.t t/*/*.t'); WriteAll;
#t/00_compile.t use strict; use Test::More; plan(tests=>1); use_ok("Example::Software");
モジュールのインストール
cpan install inc::Module::install cpan install Test::Harness; cpan install Test::More;
実行方法
make clean perl Makefile.PL make make test
proveによる実行方法
prooveはTest::Harnessに梱包されているツール。
テスト結果のカラー出力と、テスト実行時間の計測が可能。
#テストディレクトリ(t)配下をすべて実行する。※すべてのテストを実行する cd Example-Software prove -vlr t
Test::Moreの基本的な関数
#値が真か確認 ok($true_or_false,'test'); #classがuseできるか確認 use_ok($class,@args); #構造体が一緒 use strict; use Test::More; plan(tests=>1); my $hash = {foo=>1}; my $expect = {foo=>2} is_deeply($hash,$expect,'構造体が一致') or dialog(explain($hash)); #期待値と一致するか is($value,'期待値','$valueが期待値と一致するか確認'); #正規表現と一致するか like($value,qr/正規表現/,'$valueが正規表現と一致するか確認');
具体的なテスト例
例)動作させるコード
sub is_even{ my $n = shift; if($n != int($n)){ die "not integer"; } if($n < -100 || $n > 100){ die "-100 ~ 100"; } return $n % 2 == 0; }
例)それに対するテストコード
use strict; use warnings; use Test::More; plan(tests=>9); use Test::Exception; my @data = ( [-42,1], [4,1], [-11,0], [97,0], [34,1], [-21.5, qr/not integer/], [4.1, qr/not integer/], [4.2, qr/not integer/], [1.6, qr/not integer/], [-1000,qr/-100~100/], [-101,qr/-100~100/], [-100,1], [-99,0], ); foreach my $testcase(@data){ my($n,$expect_even)=@$testcase; if(ref $expect_even eq 'Regexp'){ throws_ok{is_even($n)}$expect_even, (defined $n ? "(undef)" : $n). "should throw an exception"; }elsif($expect_event){ ok(is_even($n),"$n should be even"); }else{ ok(!is_even($n),"$n should not be even"); } }