13

我正在编写一个 Perl 模块,并且我正在使用 carp 向调用程序抛出一个非致命警告。

carp 警告工作正常 - 我正在检查输入参数是否满足特定条件 - 如果它不满足条件,则会使用 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 没有最好的理解——也许这不是捕捉 carp 警告输出的最佳方法。我尝试使用 $SIG{__WARN__},但那也是空的。

有什么方法可以捕获鲤鱼的输出吗?这不是最大的问题,因为这只是在我的测试脚本中,但我仍然想让我的测试脚本正常工作。

提前致谢!

4

3 回答 3

20

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

local $SIG{__WARN__} = sub { die $_[0] };
eval $proggie;
于 2009-01-27T15:00:44.217 回答
7

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

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';
于 2009-01-27T16:06:23.943 回答
6

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

于 2009-01-27T18:09:01.467 回答