2009-01-27 13 views
13

我正在写一个Perl模块,并且我正在使用鲤鱼向调用程序返回非致命警告。如何在Perl中捕捉鲤鱼的输出?

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

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

我的模块看起来是这样的:

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

和我的测试脚本是这样的:

eval { 
    #call to my module 
}; 
like (
    [email protected], 
    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},但那也是空的。

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

在此先感谢!

回答

19

从这个页面,http://perldoc.perl.org/perlvar.html,它看起来像你想设置本地$SIG{__WARN__}到一个子例程,将警告转变为测试脚本的致命错误。他们给出的例子是:

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

是的,这是诀窍!我误解了$ SIG {__ WARN__}是什么。这完美 - 非常感谢! – BrianH 2009-01-27 15:09:52

6

另一种方式如何捕捉警告,也都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'; 
+0

哇 - 非常有趣。第一个例子非常简单,看起来也很好。 – BrianH 2009-01-27 16:52:08

6

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

+0

这看起来像一个非常简单的解决方案。不幸的是我没有在我们的环境中安装Test :: Output,并且在这里安装模块几乎是不鼓励的。即使它不符合我的需求,+1也是一个很好的解决方案。 – BrianH 2009-01-27 19:11:02