2011-06-04 70 views
4

我的代碼對糟糕的API調用進行了測試,幸運的是,代碼導致模塊本身發出警告。但是當我測試失敗的API調用時,我想在TAP中看不到警告。在TAP中靜音警告

t/01-pass.t .............. ok 
t/02-fail.t .............. ok 
t/03-noversion.t ......... ok 
t/04-no-file.t ........... ok 
Use of uninitialized value $file in concatenation (.) or string at /home/xenoterracide/projects/Test-Version/lib/Test/Version.pm line 29. 
t/05-file-not-defined.t .. ok 
# unsorted oks: 001 
t/06-all.t ............... ok 
All tests successful. 
Files=6, Tests=37, 1 wallclock secs (0.04 usr 0.02 sys + 0.35 cusr 0.04 csys = 0.45 CPU) 
Result: PASS 

下面是實際的代碼

#!/usr/bin/perl 
use 5.006; 
use strict; 
use warnings; 
use Test::Tester tests => 7; 
use Test::Version qw(version_ok); 

check_test(
    sub { 
     version_ok; # correct call version_ok($file) 
    }, 
    { 
     ok => 0, 
     name => 'check version in ', 
     diag => 'FILE_NOT_DEFINED', 
    }, 
    '$file not defined' 
); 

有沒有什麼辦法來壓制警告和預防,以防止它(原模塊中的no warnings外)在TAP 結束了。

+0

您應該修復代碼,以便在給出不正確的參數時不會發出警告。 – Schwern 2011-06-05 01:55:19

+0

@schwern爲什麼?它會放棄並無法通過測試,這是它應該做的。代碼不應該沒有參數...我想知道的是,測試正常返回失敗 – xenoterracide 2011-06-05 03:46:18

+0

@xenoterracide 1)它表示代碼沒有真正考慮過的情況,它的工作可能是巧合。 2)由於你沒有拋出異常(它可能應該拋出一個異常),因此在生產過程中,你將會得到該警告並阻塞日誌,並使讀者分心,而不是真正的問題。 3)在測試中,你必須做很多工作來壓制警告(和*只是*警告)以修復它。 4)如果你不這樣做,只需關閉該運行的所有警告,稍後可能會掩蓋另一個重要警告。 – Schwern 2011-06-05 19:54:41

回答

4
local $SIG{__WARN__} = sub {}; 

會暫時使警告無效。

+0

簡單,有效,不需要我添加大量其他依賴關係或找出任何新代碼,並且很容易限制在函數調用上方的區域。 – xenoterracide 2011-06-05 04:03:55

+1

我建議不要關閉代碼的所有警告。你現在禁止一個已知的警告,但更改可能會在稍後引入,並且你永遠不會看到它。禁止警告是一個非常滑的斜坡,不應掉以輕心。 – Schwern 2011-06-05 19:55:50

+0

@xenoterracide:如果你打算這樣做,我會把處理程序改爲'sub {push @warnings,@_}'(在子外部定義'@ warnings')並檢查它是否包含* only * your預期給定測試的警告。當然,在這一點上,你可能只是使用Test :: Warn,或者首先防止警告。 – 2011-06-06 14:21:13

6

您可能正在尋找Test::Warn。它很容易使用:

use strict; 
use warnings; 
use Test::More; 
use Test::Warn; 
# You might also find the following modules interesting: 
# use Test::Exception; 
# use Test::NoWarnings; 

sub bla { warn 'bla' } 

warning_is { bla() } 'bla'; 
done_testing; 

所以,你正在從一個令人討厭的警告轉化爲預期的東西。

如果這不是你想要什麼,然後看看IO::CaptureOutput或 - 德偏好,根據這兩個模塊,大衛·金的作者 - 在Capture::Tiny

您也可以通過手動將STDERR重定向到緩衝區,以便在發出呼叫時發出警告。

+0

Test :: Warn用於測試是否發生預期的警告。也就是說,這是一個界面的一部分。 OP的警告並非如此,這是一個正確的警告,告訴OP,代碼沒有很好地寫入來處理沒有爭論。 – Schwern 2011-06-05 01:57:24

+0

@Schwern,你是對的。看起來對於OP來說,'$ SIG {__ WARN__} = sub {}'是最合適的解決方案。 – Lumi 2011-06-05 09:43:38

+0

我會這樣做,如果它不是因爲我將不得不弄清楚如何得到這個內部的Test :: Tester測試。我在該塊的'version_ok'之上放置了'local $ SIG {__ WARN__} = sub {};'。然而,包裹一個子包裹,包裹一個包裹子或任何東西傷害我的大腦。另外我不確定我是否想爲一個測試添加另一個依賴項。 @schwern修補程序歡迎Test :: Version修復version_ok,以便它不會生成警告。 – xenoterracide 2011-06-08 12:10:04

0

要考慮的另一個警告相關模塊是Test::NoWarnings。這會檢查您的代碼是否不會產生警告,如果不是,則會通過測試。您可以忽略已知警告,例如OP,假設這是所需的行爲(在$ work,我們忽略來自少數「嘈雜」CPAN模塊(例如PDF :: API2)的警告)。它可以

一般來說,我會同意Schwern,雖然,並嘗試修復警告,而不是覆蓋$SIG{__WARN__}覆蓋。測試的一個主要好處是捕獲當其他代碼發生更改時引入的錯誤 - 您的測試文件不只是檢查您剛寫入的代碼是否正常,而且您編寫的代碼仍然可以正常運行未來當CPAN模塊和其他應用程序將被更新時。

+0

我同意一般來說這是一個壞主意。每個人都有一種失落的焦點,這是專門爲這個模塊編寫的6個測試之一(意思是沒有人打擾去閱讀Test :: Version),並且只有**其中一個我已經完成了這個測試。是檢查一個不好的api調用,並且爲此打印診斷信息。 我可以將Test :: NoWarnings添加到應該工作的API的良好運行中,並且運行得很好。基本上,整個測試是說,寫的代碼是**不是**就好,測試失敗。 – xenoterracide 2011-06-08 12:02:06