【问题标题】:How can I catch the output from a carp in Perl?如何在 Perl 中捕获鲤鱼的输出?
【发布时间】:2010-10-03 18:34:40
【问题描述】:

我正在编写一个 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__},但它也是空的。

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

提前致谢!

【问题讨论】:

    标签: perl warnings try-catch


    【解决方案1】:

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

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

    【讨论】:

    • 是的,这就是诀窍!我误解了 $SIG{WARN} 是什么。这非常有效 - 非常感谢!
    【解决方案2】:

    如何捕获警告以及所有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';
    

    【讨论】:

    • 哇——非常有趣。第一个示例非常简单明了,而且看起来效果也很好。
    【解决方案3】:

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

    【讨论】:

    • 这看起来是一个非常简单的解决方案。不幸的是,我没有在我们的环境中安装 Test::Output,在这里安装模块是非常不鼓励的。即使它不符合我的需求,+1 也是一个很好的解决方案。
    猜你喜欢
    • 2011-02-18
    • 2020-04-29
    • 2015-11-16
    • 2012-01-06
    • 1970-01-01
    • 2012-07-15
    • 2021-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多