2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

標準出力に対してテストをする

Posted at

標準出力のテストをする

みなさん!perl書いてますか?

今回は、標準出力に対してテスト方法をご紹介します。

使用モジュール

テストで使用するモジュールといえば、 Test::More です! (標準モジュール)

使い方などについては、下記のサイトがわかりやすいです。

ということで使い方の説明は、省略しますです。

テストのとき、
関数からの戻り値は、簡単にテストできるのですが、
標準出力される文字(print)などは、テストしにくいですよね・・・。

そこで今回ご紹介したいのが Test::Trap というモジュールです。

標準モジュールではないので、いつものコマンドでまずはインストールします。

$ cpanm -v Test::Trap

このモジュールを簡単に説明すると・・・

  • 実行したコードの標準出力などが簡単に取得できる
  • プログラムの終了コード・標準エラー出力なども取得可能

試してみましょう

例として、以下の3パターンのテストしてみます。

  • プログラムの終了ステータス
  • 標準出力
  • 標準エラー出力

下記のTargetモジュールに対して、テストをしていきます。

Target.pm
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を使用します。

テスト対象(Target.pm)
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を使用します。

テスト対象(Target.pm)
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を使用します。

テスト対象(Target.pm)
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の場合

テスト対象(Target.pm)
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を使います。

テスト対象(Target.pm)
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のページを見ると他にもできることがありそうなので、試してみてくださいね!

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?