標準出力のテストをする
みなさん!perl書いてますか?
今回は、標準出力に対してテスト方法をご紹介します。
使用モジュール
テストで使用するモジュールといえば、 Test::More
です! (標準モジュール)
- Test::More - yet another framework for writing test scripts - metacpan.org
- https://metacpan.org/pod/Test::More
使い方などについては、下記のサイトがわかりやすいです。
-
Test::More - テストを書くためのもう一つのフレームワーク - perldoc.jp
-
http://perldoc.jp/docs/modules/Test-Simple-0.99/lib/Test/More.pod
-
Test::More - 自動テストのためのテストプログラムを書く - Perl入門ゼミ
ということで使い方の説明は、省略しますです。
テストのとき、
関数からの戻り値は、簡単にテストできるのですが、
標準出力される文字(print)などは、テストしにくいですよね・・・。
そこで今回ご紹介したいのが Test::Trap
というモジュールです。
- Test::Trap - Trap exit codes, exceptions, output, etc. - metacpan.org
- https://metacpan.org/pod/Test::Trap
標準モジュールではないので、いつものコマンドでまずはインストールします。
$ cpanm -v Test::Trap
このモジュールを簡単に説明すると・・・
- 実行したコードの標準出力などが簡単に取得できる
- プログラムの終了コード・標準エラー出力なども取得可能
試してみましょう
例として、以下の3パターンのテストしてみます。
- プログラムの終了ステータス
- 標準出力
- 標準エラー出力
下記のTarget
モジュールに対して、テストをしていきます。
package Target;
use Object::Simple -base;
sub exit_ok {
my $self = shift;
exit 0; # 正常終了
}
sub exit_error {
my $self = shift;
exit 1; # 異常終了
}
sub print_hoge_stdout {
my $self = shift;
print "hoge!"; # 標準出力
}
sub print_fuga_stderr {
my $self = shift;
print STDERR "fuga!"; # 標準エラー出力
}
sub print_piyo_warn {
my $self = shift;
warn "piyo!"; # 標準エラー出力
}
sub die_foo {
my $self = shift;
die "foo"; # 標準エラー出力
}
1;
使い方
trap {(実行コード)}
trap内の実行コード
が処理されると、$trap
に結果が入ります。
あとは、取得したい出力などをTest::Trapの関数を実行して取得します。
use Test::More;
use Test::Trap;
trap {(実行コード)};
is $trap->(Test::Trapの関数), (期待値), "(テスト名)";
done_testing;
ということで、実際に試してみます。
テスト: プログラムの終了ステータス
プログラムの終了ステータスを取得したいときは、$trap->exit
を使用します。
sub exit_ok {
my $self = shift;
exit 0; # 正常終了
}
sub exit_error {
my $self = shift;
exit 1; # 異常終了
}
use strict;
use warnings;
use utf8;
use Test::More;
use Test::Trap;
use Target;
my $target = Target->new;
# 正常終了
trap { $target->exit_ok };
is $trap->exit, 0, "exit_ok";
# 異常終了
trap { $target->exit_error };
is $trap->exit, 1, "exit_error";
done_testing;
ok 1 - exit_ok
ok 2 - exit_error
1..2
すべてのテストが成功しました。
ちなみに間違っていると・・・
use strict;
use warnings;
use utf8;
use Test::More;
use Test::Trap;
use Target;
my $target = Target->new;
# 正常終了
trap { $target->exit_ok };
is $trap->exit, 0, "exit_ok";
# 異常終了
trap { $target->exit_error };
is $trap->exit, 0, "exit_error"; # NG!!
done_testing;
ok 1 - exit_ok
not ok 2 - exit_error
# Failed test 'exit_error'
# at hoge.t line 16.
# got: '1'
# expected: '0'
1..2
# Looks like you failed 1 test of 2.
上記の例だと「コードの実行結果が1
で期待値は0
でした」と表示されてテストが失敗します。
テスト: 標準出力
標準出力を取得したいときは、$trap->stdout
を使用します。
sub print_hoge_stdout {
my $self = shift;
print "hoge!"; # 標準出力
}
use strict;
use warnings;
use utf8;
use Test::More;
use Test::Trap;
use Target;
my $target = Target->new;
trap { $target->print_hoge_stdout };
is $trap->stdout, "hoge!", "print_hoge_stdout";
done_testing;
ok 1 - print_hoge_stdout
1..1
テスト: 標準エラー出力
標準エラー出力を取得したいときは、$trap->stderr
を使用します。
sub print_fuga_stderr {
my $self = shift;
print STDERR "fuga!"; # 標準エラー出力
}
use strict;
use warnings;
use utf8;
use Test::More;
use Test::Trap;
use Target;
my $target = Target->new;
trap { $target->print_fuga_stderr };
is $trap->stderr, "fuga!", "print_fuga_stderr";
done_testing;
ok 1 - print_fuga_stderr
1..1
warnの場合
sub print_piyo_warn {
my $self = shift;
warn "piyo!"; # 標準エラー出力
}
warnが実行されると、piyo! at Target.pm line 31.
というようなメッセージが標準エラー出力にでます。
指定した文字列の後ろにファイル名や行数が追加されてきてしまい、固定的な文字(完全に一致)ではテストしにくそうです。
※行数が変更になったり、ファイルがリネームされたりしたらテストが失敗してしまうようになる
そんなときは、Test::Moreのlike
が便利です。
正規表現で期待値を設定できます。
use strict;
use warnings;
use utf8;
use Test::More;
use Test::Trap;
use Target;
my $target = Target->new;
trap { $target->print_piyo_warn };
like $trap->stderr, qr/^piyo!/, "print_piyo_warn";
done_testing;
ok 1 - print_piyo_warn
1..1
dieの場合
dieのときは、Test::Trapの:die
を明示的にインポートして$trap->die
を使います。
sub die_foo {
my $self = shift;
die "foo"; # 標準エラー出力
}
dieもwarnと同じく実行された行の情報が後ろにつくのでlike
でテストを書いておきます。
use strict;
use warnings;
use utf8;
use Test::More;
use Test::Trap qw/:die/;
use Target;
my $target = Target->new;
trap { $target->die_foo };
like $trap->die, qr/^foo/, "die_foo";
done_testing;
ok 1 - die_foo
1..1
まとめ
このようにTest::Trap
を使用すると、標準出力などが簡単にテストできます。
Test::Trapのページを見ると他にもできることがありそうなので、試してみてくださいね!
- Test::Trap - Trap exit codes, exceptions, output, etc. - metacpan.org
- https://metacpan.org/pod/Test::Trap