nysus has asked for the wisdom of the Perl Monks concerning the following question:

I have a test file with Test::NoWarnings. The module getting tested relies on other module that use XS. One of those modules throws a warning that it's "falling back to PP version". This warning causes my test to fail. I tried the following to fix the issue:

use strict; use warnings; use File::Path; use Data::Dumper qw(Dumper); use Test::NoWarnings; use Test::Output; use Test::Most tests => 16, 'die'; BEGIN { $ENV{'DANCER_ENVIRONMENT'} = 'testing'; $SIG{__WARN__} = sub { my $warn = shift; return if $warn =~ /fallback to PP version/; warn $warn; }; }

While this does suppress the warning, it also suppresses all warnings that my test might produce making Test::NoWarnings useless. As a workaround, I just comment out the $SIG{__WARN__} stuff while I'm testing but I'd like to learn how to properly address this issue. I tried moving it outside the BEGIN block but that didn't help. Thanks!

$PM = "Perl Monk's";
$MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
$nysus = $PM . ' ' . $MCF;
Click here if you love Perl Monks

Replies are listed 'Best First'.
Re: What is the proper way to suppress a warning in a test file?
by choroba (Cardinal) on Nov 08, 2018 at 18:08 UTC
    It seems Test::NoWarnings uses the __WARN__ signal handler to do its magic, so you need to call the handler it installed after having processed the warning in your handler.
    #!/usr/bin/perl use warnings; use strict; use Test::NoWarnings; use Test::More tests => 2; my $old = $SIG{__WARN__}; $SIG{__WARN__} = sub { my ($w) = @_; return if $w =~ /Eh/; warn $w; $old->(@_) if $old; }; ok(1); warn 'Eh'; # Will be ignored. warn 'Error'; # Will be reported.

    At work, we use Test::Warnings instead (it handles done_testing() correctly). The solution is similar for this module, you just don't need to rewarn:

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: What is the proper way to suppress a warning in a test file?
by haukex (Archbishop) on Nov 08, 2018 at 18:14 UTC

    Personally, when I send code to CPAN and therefore CPAN Testers, I no longer rely on an exact number of warnings, because I've had issues with that: new versions of Perl may introduce new warnings, old versions of Perl may have warnings that you weren't expecting, and even different OSes might be different. Instead, I would suggest to either test for the presence of specific warnings that one's own code produces, or to test for the absence of specific warnings that should definitely not happen. Update: "No warnings at all" is fine if you're running one version of Perl on one OS, but once that changes, you can't necessarily rely on it. You can of course also try to modify your code to eliminate all warnings on all OSes and Perl versions, that would be optimal, but as you're discovering, that's not always feasible. Or, you can write your tests to expect those warnings, but that's of course not "no warnings at all".

      Interesting. I guess the biggest reason I keep it around is the "uninitialized value" warning as well as other warnings that signal my code is sloppy. How do you check for the "specific warning that definitely should not happen?"

      $PM = "Perl Monk's";
      $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
      $nysus = $PM . ' ' . $MCF;
      Click here if you love Perl Monks

        How do you check for the "specific warning that definitely should not happen?"

        I have a simple little function that I include in my test libraries, for example:

        sub warns (&) { my $sub = shift; my @warns; { local $SIG{__WARN__} = sub { push @warns, shift }; $sub->() } return wantarray ? @warns : scalar @warns; }

        Then I'll use it like this:

        sub some_module_code { my $arg = shift; warn "Some custom warning about $arg"; } my @w = warns { some_module_code("foo"); }; is grep({/\bSome custom warning\b/i} @w), 1; is grep({/\bUse of uninitialized value\b/i} @w), 0;