テストをはじめる (標準出力する関数のテスト)

foo.pl

use strict;
use warnings;

sub my_print{
 my $c = shift;
 $c . "\n";
}

1;

foo.t

use strict;
use warnings;

use Test::More 'no_plan';
require 'foo.pl';

ok( my_print('First Test') eq 'First Test' . "\n");

実行

$ perl foo.t
ok 1
1..1

ここまでは簡単なんだが

foo.pl がこのようにprintしていて、
print したものが正しいか調べるのはむずかしい。どうすれば....

use strict;
use warnings;

sub my_print{
 my $c = shift;
 print $c . "\n";
}

1;

tieのやりかたがあったのでやってみる

tieでSTDOUTをつかまえる - 徒書

tieというと私の最新の記事である

ビンゴ中西のほげほげPerl で遊んでみる その1

標準出力とかと使うときはこうなるのか

ファイルハンドルの tie (mixi 日記アーカイブ)

使わせていただくと

use strict;
use warnings;

use Test::More 'no_plan';
require 'foo.pl';

{
    # 出力を変数に溜めるためのクラス
    package POOL;
    use overload (
         q{""} => sub { ${$_[0]} }
    );
    sub TIEHANDLE {
        my $str;
        bless \$str, $_[0];
    }
    sub PRINT {
        my $self = shift;
        $$self .= $_ for @_;
    }
}

my $pool;
{
  $pool = tie local *STDOUT, 'POOL';
  my_print('First Test');
}

ok( $$pool eq 'First Test' . "\n" );
ok( $$pool eq 'Firt Test' . "\n" );

実行

$ perl foo.t
ok 1
not ok 2
#   Failed test at foo.t line 30.
1..2
# Looks like you failed 1 test of 2.

うまくいっている。

$poolをDumperでみておこう

use strict;
use warnings;
use Data::Dumper;

require 'foo.pl';

{
    # 出力を変数に溜めるためのクラス
    package POOL;
    use overload (
         q{""} => sub { ${$_[0]} }
    );
    sub TIEHANDLE {
        my $str;
        bless \$str, $_[0];
    }
    sub PRINT {
        my $self = shift;
        $$self .= $_ for @_;
    }
}

my $pool;
{
  $pool = tie local *STDOUT, 'POOL';
  my_print('First Test');
}

print Dumper $pool;

結果

$ perl foo.t
$VAR1 = bless( do{\(my $o = 'First Test
')}, 'POOL' );

うん。思った通り。

標準出力をどうしたかったのか(一応、説明)

my_print('hoge')というのを、実行すると中でprintしてるから、出力されちゃう。でも、

$pool = my_print('hoge');

として、出力される内容を変数にいれたい。
でも、それはできないので、魔法をかけて

my_print('hoge');

としただけで、$poolに代入されたイメージ。

PHPだと

PHP: 出力制御 - Manual
なんかがあるらしい。