Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

How not to test exceptions

by jk2addict (Chaplain)
on Jul 22, 2005 at 00:16 UTC ( #477062=perlmeditation: print w/replies, xml ) Need Help??

I posted this over at use.perl. I figured I'd stuff it here some someone else may learn from my pain.

I'm such and idiot. I can't believe I never noticed this before. It's quite a dangerous oversight too since it meant tests didn't register a pass or a fail; no output at all which threw off the test counts. Don't let this happen to you.

---some.t--- use Test::More tests => 2; use Error ':try'; use_ok('MyModule'); try { MyModule->foo('badparam'); } catch with MyModule::Exception { pass; } otherwise { fail; }

Of course, if the module throws the exception, we pass. If it throws another exception (or die), we fail. But, if the module unexpectedly succeeds, we neither fail nor pass. That's not so bad right? THe count mismatch would cause the test to fail right? Sure, but picture this:

---some.t--- use Test::More tests => 2; use Error ':try'; use_ok('MyModule'); try { MyModule->foo('badparam'); } catch with MyModule::Exception { pass; } otherwise { fail; } ok('added this test later in this huge test file');

In this scenerio, you've added a test but forgot to update the test plan count. Now you've declared 2 tests and passed 2 tests. No failures and you never know a completely failing test...didn't. This is ever more true if you're using no_plan. Probably another reason not to ever do that. :-)

Ths answer of course is to put a fail in the try block. Not something that seams obvious upon first thought.

---some.t--- use Test::More tests => 2; use Error ':try'; use_ok('MyModule'); try { MyModule->foo('badparam'); fail; } catch with MyModule::Exception { pass; } otherwise { fail; }

Boy do I have a lot of test files to double check. That was a painful lesson.

Replies are listed 'Best First'.
Re: How not to test exceptions
by diotalevi (Canon) on Jul 22, 2005 at 01:15 UTC

      That's good info. I wish it was mentioned in its pod. For now I'm ok I think based on the fact that I don't actually use try/catch in the code (maybe once), but I just use throw within the code when things go wrong. It sounds like the problems would more effect people using the dist catching MY exceptions in their code.

      Is there a decent replacement that can be shoehorned easily? Time to surf CPAN...

      Updated. Not that Error isn't evil based on others experience, but AxKit uses Error. It can't be all that bad. I've looked ad Exception, but the lack of the 'catch with' sugar annoys me so...Exceptions are try/catch after all.

        The problems Error has are introduced when you introduce the sugar which is why any Exception using code which avoids this error will also avoid the sugar. You can't get that sugar without also introducing that class of bugs. Its inherent.
Re: How not to test exceptions
by itub (Priest) on Jul 22, 2005 at 02:11 UTC
    I usually test my exceptions using Test::Exception, but I don't know if it plays well with the Error module.
      I usually test my exceptions using Test::Exception, but I don't know if it plays well with the Error module.

      It should behave perfectly. Error is just some syntactic sugar around Perl's normal exception handling system. The OP's test would become the IMHO much more readable:

      use Test::More tests => 2; use Test::Exception; BEGIN { use_ok( 'MyModule' ) }; throws_ok { MyModule->foo( 'badparam'' ) } 'MyModule::Exception';
Re: How not to test exceptions
by jk2addict (Chaplain) on Jul 22, 2005 at 12:51 UTC
    The main reason I stayed away from Test::Exception was that I didn't want to skip all of the exceptions tests just because it wasn't installed. That is even more true when I can do much of the same with Error/try, AND the fact that Error is already a PREREQ for the dist being tested.
      The main reason I stayed away from Test::Exception was that I didn't want to skip all of the exceptions tests just because it wasn't installed.

      Then add it as a prerequisite so it gets installed :-)

      That is even more true when I can do much of the same with Error/try

      Well you have to type a heck of a lot more by using raw try/catch from Error, as you've seen doing so is prone to error, and you get far less useful messages on test failure.

      AND the fact that Error is already a PREREQ for the dist being tested.

      If you really don't want to add another prerequisite to the installation, add a local copy of Test::Exception and its dependencies to t/lib and just use it in your test scripts. The module is pure perl.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://477062]
Approved by atcroft
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (3)
As of 2022-01-18 04:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    In 2022, my preferred method to securely store passwords is:












    Results (52 votes). Check out past polls.

    Notices?