如何在Perl中捕获鲤鱼的输出?

时间:2009-01-27 14:36:05

标签: perl warnings try-catch

我正在编写一个Perl模块,我正在使用carp将非致命警告发送回调用程序。

鲤鱼警告工作正常 - 我正在检查输入参数是否满足某个条件 - 如果它不符合条件,则会发送警告并且模块继续使用参数的默认值而不是调用程序通过了。警告只是通知正在使用默认参数而不是传入的参数。

我的问题在于我的测试脚本。我的测试脚本正在向模块发送一个错误的参数,我正在尝试捕获返回的警告消息,并确保我收到了正确的警告消息。

我的模块看起来像这样:

else {
  carp "value must be numeric - using default value";
}

我的测试脚本如下所示:

eval {
  #call to my module
};
like (
    $@,
    qr/value must be numeric/,
    "Should abort on non-numeric value"
);

当我运行测试时,我可以在屏幕上看到警告(它必须是STDERR),但$ @变量的内容是' - 空白。

以下是我的测试脚本的输出:

t/04bad_method_calls....ok 10/12value must be numeric - using default value at ...
#   Failed test 'Should abort on non-numeric value'
#   at t/04bad_method_calls.t line 98.
t/04bad_method_calls....NOK 12
#                   '' doesn't match '(?-xism:value must be numeric)'
# Looks like you failed 1 test of 12.

如果我将鲤鱼更改为呱呱叫,我的测试脚本有效 - 它会捕获错误消息(但我只想警告,而不是中止)。

老实说,我对eval没有最好的理解 - 也许这不是捕捉鲤鱼警告输出的最佳方法。我尝试使用$ SIG { WARN },但这也是空的。

有没有办法捕获鲤鱼的输出?这不是最大的交易,因为这只是在我的测试脚本中,但我仍然希望让我的测试脚本正常工作。

提前致谢!

3 个答案:

答案 0 :(得分:19)

在此页面http://perldoc.perl.org/perlvar.html中,您似乎希望将本地$SIG{__WARN__}设置为一个子例程,该子例程会将警告转换为测试脚本的致命错误。他们给出的例子是:

local $SIG{__WARN__} = sub { die $_[0] };
eval $proggie;

答案 1 :(得分:7)

另一种捕获警告的方法以及所有STERR输出:

my $stderr = '';
{
    local *STDERR;
    open STDERR, '>', \$stderr;
    do_stuf_here();
}
like( $stderr, qr/my result/, 'test stderr output' );

可以制作奇特的测试功能:

sub stderr_test (&$$) {
    my ( $code, $pattern, $text ) = @_;
    my $result = '';
    {
        local *STDERR;
        open STDERR, '>', \$result;
        $code->();
    }
    if ( UNIVERSAL::isa( $pattern, 'Regexp' ) ) {
        like( $result, $pattern, $text );
    }
    else {
        is( $result, $pattern, $text );
    }
}

# usage
stderr_test {do_stuf_here} qr/my expected STDERR output/,
    'stderr is like';
stderr_test {do_stuf_here} 'my expected STDERR output',
    'stderr is exactly';

答案 2 :(得分:6)

如果您是从测试脚本执行此操作,则可以使用为您捕获输出的Test :: *模块。我倾向于Test::Output