我試圖用Test::More單元測試打印到屏幕上的Perl函數。我該如何測試打印到屏幕上的Perl函數?
我知道這個輸出可能會干擾工具,如prove。
如何捕獲此輸出以便我可以使用diag()
進行打印,還可以對輸出本身執行測試?
我試圖用Test::More單元測試打印到屏幕上的Perl函數。我該如何測試打印到屏幕上的Perl函數?
我知道這個輸出可能會干擾工具,如prove。
如何捕獲此輸出以便我可以使用diag()
進行打印,還可以對輸出本身執行測試?
UPDATE:恕我直言,正確回答這個問題應該是使用Test::Output:
#!/usr/bin/perl
use strict; use warnings;
use Test::More tests => 1;
use Test::Output;
sub myfunc { print "This is a test\n" }
stdout_is(\&myfunc, "This is a test\n", 'myfunc() returns test output');
輸出:
C:\Temp> tm 1..1 ok 1 - myfunc() returns test output
我離開了原來的答案供參考,我相信,它仍然說明了一種有用的技術。
您可以本地化STDOUT
和調用函數之前重新打開一個標,恢復後:
#!/usr/bin/perl
use strict; use warnings;
use Test::More tests => 1;
sub myfunc { print "This is a test\n" }
sub invoke {
my $sub = shift;
my $stdout;
{
local *STDOUT;
open STDOUT, '>', \$stdout
or die "Cannot open STDOUT to a scalar: $!";
$sub->(@_);
close STDOUT
or die "Cannot close redirected STDOUT: $!";
}
return $stdout;
}
chomp(my $ret = invoke(\&myfunc));
ok($ret eq "This is a test", "myfunc() prints test string");
diag("myfunc() printed '$ret'");
輸出:
C:\Temp> tm 1..1 ok 1 - myfunc() prints test string # myfunc() printed 'This is a test'
對於perl
版本比5.8老,你可能需要使用IO::Scalar,但我對5.8之前的工作情況瞭解不多。
如果這是您正在編寫的代碼,請對其進行更改以使打印語句不使用默認文件句柄。相反,給自己一個方法來設置輸出文件句柄到你喜歡的東西:
sub my_print { my $self = shift; my $fh = $self->_get_output_fh; print { $fh } @_; } sub _get_output_fh { $_[0]->{_output} || \*STDOUT } sub _set_output_fh { $_[0]->{_output} = $_[1] } # add validation yourself
當你測試,你可以調用_set_output_fh
給它您的測試文件句柄(甚至可能是一個IO::Null手柄)。當另一個人想要使用你的代碼但是捕獲輸出時,他們不必向後彎曲,因爲他們可以提供自己的文件句柄。
當您發現難以測試的部分代碼或者您必須跳過這些環節才能使用時,您的設計可能很糟糕。我仍然對測試代碼如何使這些事情變得明顯感到驚訝,因爲我經常不會考慮它們。如果很難測試,可以很容易測試。如果你這樣做,你一般會贏。
阿門。編寫單元測試(或者如果您使用TDD進行計劃,無論您是否知道)通常都會導致設計上的顯着改進。 – DVK 2009-10-09 03:37:14
正當我想我在這麼浪費太多時間時,我學到了一些很酷的東西!謝謝。 – FMc 2009-10-08 15:50:30
呃,從技術上說他們不這樣做,但是他們確實很好。 :p(+1,這是一個很棒的模塊) – 2009-10-08 19:08:04
我沒有降低它的效果,但我認爲原始答案做了太多的工作來完成工作。它太複雜了。儘管我對Test :: Output有點偏向,但我將它作爲最後的手段。 – 2009-10-08 23:13:09