スクリプトからサブルーチンだけをインポートする
Script::Sub::Importというモジュールを作成しました
http://d.hatena.ne.jp/perlcodesample/20091130/1258979624
命題はスクリプト内で使っている関数のテストをしたい、なんだよね。
なら、いくつかこんなひどいハックじゃないやり方がある。
まず第一の、そして一番まともな方法としては「モジュール化」を考えるべき。元のスクリプトがこんな感じだとする:
#!/usr/bin/perl
use strict;
main();
sub main {
# pseudocode...
foo(@ARGV);
bar();
}
sub foo { ... }
sub bar { ... }
だったら、こんなlib/MyApp.pmを作って、そこにこんなコードを書いておけばいい:
package MyApp;
use strict;
sub foo { ... }
sub bar { ... }
で、以下のようにスクリプト内で呼び出せばいい。
#!/usr/bin/perl
use strict;
use MyApp;
main();
sub main {
MyApp::foo(@ARGV);
MyApp::bar();
}
これならテストはそれこそ普通のモジュールのテストを書くときのようにすればいい。
でもモジュール化したくない時というのもわかる。例えばlibディレクトリを使わずにスクリプト単体で完結させたい、なんて状況も考えられる。なのでそれは理解できるのだが、それなら以下のように caller()を確認すればメイン関数は走らないので、スクリプトの実行はせずに関数群をrequireできるようになる。
#!/usr/bin/perl
use strict;
main() unless caller(); # perl script.plで呼び出された時は空配列が返るのでmain()実行
# テストスクリプトやその他の場所から呼び出された場合は
# なんらかの値が返るので、実行されない
sub main { ... }
sub foo { ... }
sub bar { ... }
これなら、普通にテストスクリプトでrequireなりなんなりして、スクリプト内の関数をぼこっと使える:
# テストファイル
require 'script.pl';
ok( foo( ... ) );
is( bar(...) );
caller()の手法の代わりに$ENV{TEST}みたいなフラグを使うのもありだろう。
追記:そういえば書こうとして忘れてた。
@tokuhirom: .pl にはほとんど何も書かないのが最近のトレンドなんだけどな。
そうそう。ということで、こういうのでもいいわけです:
package App::MyApp;
use Moose; # or Mouse, or Class::Accessor::Fast, whatever
sub run {
my $self = shift;
$self->foo(@args);
$self->bar();
}
sub foo { ... }
sub bar { ... }
# in script.pl
use strict;
use App::MyApp;
App::MyApp->new()->run(@ARGV); # MooseX::Getoptならもっと簡単
追記終了。
いずれにせよ、いきなりCPANに登録する前に#shibya.pmで聞くとか、ブログでまずつぶやくとかしてみて、一旦回りの評価を聞いてからやってもよかったのではないか。
初心者に道を示すなら特にその辺りには気を遣って欲しいと思う。個人的にはCPANからも削除したほうがいいと思うな。