Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Testing $^W

by dws (Chancellor)
on Nov 04, 2005 at 00:36 UTC ( #505565=perlmeditation: print w/replies, xml ) Need Help??

Using -w to enable warnings is a pretty-darn-good practice when doing development in Perl. But sometimes it's necessary to turn warnings off temporarily to avoid expected warnings while doing something low-level. You do this by clearing the special variable $^W. The operative word is "temporarily". Turning off warnings without turning them back on is a pretty-darn-bad practice.

Hence a useful pair of tests to include when you're testing code that involves third-party software (i.e., stuff Not Under Your Control):

is( $^W, 1, 'warnings are on' ); third_party_code(); is( $^W, 1, 'warnings are still on' );

This test pair might save you hours of headscratching.

In some cases, the third party software you're testing might itself be blameless, falling prey to problems in its dependencies. For example, Test::MockClass uses Hook::WrapSub, which sets $^W = 0; and, for reasons I'm unable to fathom, leaves it there. (Bug report submitted.)

Replies are listed 'Best First'.
Re: Testing $^W
by tilly (Archbishop) on Nov 04, 2005 at 03:09 UTC
    Since it is a common case, I'll note that if the third_party_code() is a use statement then to make the test useful you'll need to code it in either of the following two ways.
    is( $^W, 1, 'warnings are on' ); require ThirdPartyModule; ThirdPartyModule->import; is( $^W, 1, 'warnings are still on' );
    BEGIN{is( $^W, 1, 'warnings are on' )} use ThirdPartyModule; BEGIN{is( $^W, 1, 'warnings are still on' )}
    This is because use executes at compile time, so if you write the naive version then the third party code executes before either of your tests.

    It is likely to be less confusing to use the former version because otherwise these tests will run before other tests in your test suite.

Re: Testing $^W
by Perl Mouse (Chaplain) on Nov 04, 2005 at 09:57 UTC
    Turning off warnings without turning them back on is a pretty-darn-bad practice.
    I'd say that any manual "turning warnings back on" is very bad practise. Even if you don't use use warnings (which has been available for more than 5 years), turning off warnings should be done by using a localized value for $^W, so the old value of $^W will be restored - no matter what the old value was, and no matter how the block is left.
    is( $^W, 1, 'warnings are on' ); third_party_code(); is( $^W, 1, 'warnings are still on' );
    That's only half of your tests, isn't it? What's missing is:
    { local $^W; third_party_code(); ok (!$^W, 'warnings still off'); }
    after all, you want to test that a piece of code leaves $^W as is.

    But then, why stop at testing $^W? How about $*? $"? @ARGV?, %SIG? $package::var?

    Perl --((8:>*
      But then, why stop at testing $^W? How about $*? $"? @ARGV?, %SIG? $package::var?

      I think you meant this in jest, but this would be a very valuable resource if it could be automated; kind of like the sort of utility that tests for memory leaks in C.

      Just being able to know that a given module has tampered with your { global variables/function definitions/namespaces/whatever} is very, very handy.

      Perl gives you a lot of rope to hang yourself (and others!) with; having tools to keep it coiled neatly would really be nice sometimes. :-)

        That's a great idea! I think you could add a Policy to Perl::Critic that warns you if a global or package variable was modified without being localized first.
Re: Testing $^W
by itub (Priest) on Nov 04, 2005 at 04:06 UTC

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://505565]
Approved by BrowserUk
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (2)
As of 2021-05-07 22:33 GMT
Find Nodes?
    Voting Booth?
    Perl 7 will be out ...

    Results (95 votes). Check out past polls.