# 俺の CLI コマンドの勘所2 {{tag: perl, cpan, cli}} このエントリーは [[http://qiita.com/advent-calendar/2015/perl5 Perl 5 Advent Calender 2015]] の5日目の記事です。 [[https://bayashi.net/diary/2015/1203 3日の記事]] から中一日で再び登場の bayashi です、こんにちわわわわー! 本日は、先日のエントリで書ききれなかった要素をいくらか書き足したいと思います。 ## Perl CLI ツールのテスト CLI ツールをワンライナーではなくモジュールにして利用するメリットのひとつに、テストを書いて機能の追加や変更などの運用をきちんとしやすくなるという点があります。やっぱりテストは重要ですね。 ### exitコードのテスト CLIコマンドは、時に exit するかと思います。そんな exit するコマンド実行パターンのテストは以下のように書いています(確か {{cpan: Text::Xslate}} のCLIツールのテストから拝借したまんま)。 use Test::More; my $command = 'script/randf'; # version system( $^X, (map { "-I$_" } @INC), $command, '--version' ); is $?, 256, '--version'; `--help` や invalid なオプションを渡した場合の exitコードをテストするなどにもいける。 ### 標準入力のリダイレクトと標準出力のテスト パイプで標準入力を受けつつ、標準出力に何か出すというコマンドのテストは以下のように書いている。標準出力を捕まえるのには {{cpan: Capture::Tiny}} 以外に {{cpan: Test::Output}} も便利。 use App::FromUnixtime; use Capture::Tiny qw/ capture /; use Test::More; open my $IN, '<', \<<'_INPUT_'; id 1 name John date 1419702037 _INPUT_ local *STDIN = *$IN; my ($stdout, $strerr) = capture { App::FromUnixtime->run; }; close $IN; like $stdout, qr/date\s+1419702037\([^\)]+\)/; 特に CLI どうこうというより PerlIO の話の予感。 ## CLI ツールのあり方 さて、お仕事で Perl プロジェクトやってる方々におかれましてはプロジェクト依存の CLI ツールをたくさん書くと思います。しかし、そうしたツールはある程度の数になってくると管理が大変になってきませんか? このツールなにするやつだっけ!? あれするツールどれだっけ!? なんでこのツールは使い方ないんだよ!! テスト実行かと思ったらいきなり実行されたよ!!!! とか。開発者の数が増えるごとにあるあるだと思います。 というわけで、うちのプロジェクトではそのような問題を解決するために、CLI フレームワークみたいなものに押し込んでツールを書いています(そうじゃないのもありますが)。 たとえば、プロジェクトの一大統一コマンドとして `project` というものがあります。こいつは、サブコマンドへのルーティングだけを行います。なので、`project` とだけ叩くと、サブコマンド一覧が出ます。 $ project db-user db-item memd-user memd-item logs サブコマンドは、何も引数がなければ使い方が表示されます。必ずです。 $ project db-user project db-user USER_ID -f, --full fetch relational information also 実装上は、Project::Script::Root などに親コマンドとルーティングを書いておき、Project::Script::SubCmd::* におかれたモジュールがコマンドとなって実行される感じです。たとえば、Project::Script::SubCmd::DbUser が `project db-user` として実行される。開発者は、Project::Script::SubCmd::* にモジュールを書けば良いだけ。 サブコマンド一覧は、.bashrc で補完が効くようにしておくと完璧です。 一般的なツールと違って、プロジェクトで利用する CLI ツール群はそれぞれ独立したものを書くより、このようなフレームワークに乗っけたものにしておいた方が運用面で楽ですね(といってこのやり方はまだいろいろ模索中ですが)。 というわけで、以上、俺の CLI コマンドの勘所2 でした。 明日は {{tw: karupanerura}} さんです! [[http://qiita.com/advent-calendar/2015/perl5 Perl 5 Advent Calendar 2015]] はまだまだ参加者募集中!!