monoの開発ブログ

Perl の warning をテストで検出する

Perl で use warnings を使っていて warning が出る状況というのは、プログラムに問題がある可能性が高いので潰しておきたいところです。しかし、warning が出ても普通に実行され続けてしまうので、大量のテストがあるとテストコードの出力に埋もれて warning に気付かないことも多々あります。

かといって、use warnings で FATAL を指定するのはアグレッシブすぎてこわい。

そこで、テスト中に warning が出たらテストを失敗させるという方法を考えました。まあ、検索したらすでにやっている人がいたのですが。。。

$SIG{__WARN__} = sub {
    my ($message) = @_;
    if ($message =~ /\b(?:deprecated|Use of uninitialized value|Wide character in print|Useless use of .* in void context|masks earlier declaration in same scope|experimental|isn't numeric|Odd number of elements in hash|on closed filehandle)\b/) {
        # 検出したい warning だった場合はテストを失敗させる
        fail $message;
    }
    else {
        # それ以外の warning は普通に出力する
        warn "$message";
    }
};

上記のサイトではテストを不安定にするのに留まっていますが、私がこれを使ったときは Ukigumo にそういう機能が無かったのでより厳しく warning を排除するために fail させていました。 また、\b で真面目に単語境界をチェックしていたり、on closed filehandle で閉じたファイルハンドルに対する操作を行った場合の warning も見ていたりと、微妙に変更して使っています。