nDiki : Getopt::Long

2004年7月20日 (火)

PARActivePerl 5.6.1 build 638 に

昨日 Linux 上で実験してみた PARWindows にも入れてみる。 PDLを使っている関係で ActivePerl は 5.6.1。

インストール

ppm install で入るパッケージは古いので、最新のものを入れておく。 ちょっと手間。

ワンライナーを pp できるところまで動作確認。

モジュール + スクリプトを実行可能形式に

ExtUtils::Makemakerを使ってパッケージ化している開発中のモジュール(スクリプトあり、XS あり)を実行可能形式化してみる。

 perl Makefile.PL
 nmake
 nmake test
 cd blib
 set PERL5LIB=lib;arch (pp の -I オプションが効かなかったので)
 pp -o foo.exe -a lib -a arch -M ... -c  script/foo

Log::Log4perl::Appender::Screen、Jcode::Unicode::NoXS、Unicode::StringGD については依存関係を自動検出できなかったので、それぞれ -M で指定。

できた。動いた。素晴しい。 PDLGD を使っていたのでちょっと不安だったのだがうまく動いて感激。 これでCD-ROMとか USB メモリに入れておいて一発実行とかできる。

スポンサード リンク
[ 7月20日全て ]

2004年10月18日 (月)

AppConfig

PerlのConfiguration関連のモジュールの再チェック。 Template Toolkit で使っている AppConfig が良さそげ。 設定ファイルからの設定と、コマンドラインからのオプション指定を同じ設定オブジェクトに書き込むようになっているのが便利。Getopt::Long で取得したオプションの格納先として使うだけでも便利そうだ。

設定ファイルからの再帰的設定ファイルインクルードや、コマンドラインオプションで指定した設定ファイル中の設定を「その位置」で行う機能が標準であれば嬉しいのだがさすがに無いか。 action あたりを書けば実現は可能そう。

[ 10月18日全て ]

2011年6月8日 (水)

require_ok してテスト可能な Perl スクリプトを書く

ちょっとしたものをのぞいて、Perl プログラムはアプリケーション部分も App 的 Perl モジュール(.pm)に入れて、実行するスクリプトファイル (.pl) では use して new して run するだけにしている。

 #!/usr/bin/perl

 use warnings;
 use strict;

 use MyApp; exit MyApp->new->run;

@ARGV の処理は new から呼ばれているプライベートメソッドの中で local @ARGV してから、Getopt::Long::GetOptions あたりで解析処理をしている。

でテストスクリプトではこの MyApp を use_ok して local @ARGV = qw(引数組み合わせパターン...) した後に new を呼んだ結果を検査するようにしていた。

そんなところ今回「.pm の中で @ARGV いじるのやっぱり気持ち悪くない?」っていう意見をもらった。気持ちはわかる。ただ

 MyApp->new(@ARGV)->run;

のように .pl 側で受け取ったものを解析すれば?」いいかというと、直接 @ARGV を使わない Getopt::Long::GetOptionsFromArray は 2.36 からしかなくて、古いバージョン の Getopt::Long でも動くようにすると結局 local @ARGV になってしまうのである。

また「@ARGV の解析は .pm の方には入れたくない」っていう意見もあったので、今回はそれらのコードは .pl 側に追い出すことにした。

そうすると次の課題は .pl にある @ARGV の解析処理のテストはどう書けばいいかなと。.pl ファイルを require したらスクリプトが走っちゃうし。試行錯誤していたらマスタリング Perl で紹介されている caller(0) を使う方法を教えてもらった。

caller(0) で直接実行されたのか、require されたのかで処理を変える

 スクリプトファイル(.pl)

 #!/usr/bin/perl

 package App;
 # スクリプトの実行開始エントリ
 sub main {
   # ここに実行したい処理呼び出しを書く。
 }

 main() unless caller(0);

こうするとこのスクリプトファイルを直接実行した場合は main サブルーチンが実行され、他から require された場合は main は実行されないというようにすることができる。前者の場合は caller(0) は undef を返し、後者は 'main' (あるいその他のパッケージ名)が返されることを利用している。

これでテストファイルの中でこのファイルを require_ok できるようになるので、あとは各サブルーチンのテストを書けばよい。

pod2usage の exit を回避

それから Pod::Usage を使っているんだけれど、テストでは Pod::Usage::pod2usage で exit されてしまうと困るので exit が何もしないようにしておく。テストスクリプトでは以下のようにする。

 BEGIN {
   *CORE::GLOBAL::exit = sub {};
   require_ok('script/myscript.pl');
 }

これで myscript.pl のテスト中に pod2usage が exit を呼んでもスルーさせられる。 ただし本番では exit させたい pod2usage がある場合は、その後に制御が流れていっても問題がおきないようにプログラムを書いておく必要があるので注意。

pod2usage の STDERR 出力をチェック

それから pod2usage で期待するメッセージが STDERR に吐かれているかをテストするには STDERR をオープンしなおせばよい。

 {
   my $message;
   local *STDERR;
   open STDERR, '>', \$message or die $!;
   # ここで pod2usage がメッセージを出すことが期待されるテストを実行。
   like($message, qr/expected message/);
 }

以上、スクリプトのテストについての何点かのまとめ。

[ 6月8日全て ]

About Me

Naney Naney (なにい)です。株式会社ミクシィで SNS 事業の部長をしています。

nDiki1999年1月に始めたコンピュータ日誌を前身とする NaneyWeb 日記(兼パーソナルナレッジベース)です。ちょっとしたノートは nNote にあります。

※内容は個人的見解であり所属組織とは関係ありません。

follow us in feedly

月別インデックス
Process Time: 0.052251s / load averages: 0.12, 0.27, 0.38
nDiki by WATANABE Yoshimasa (Naney, Google profile)
Powered by DiKicker