Nadim Khemir wrote:
> The bad guys:
> 
>   # Check that something died
>   dies_ok { $foo->method1 } 'expecting to die';
> 
> Am I the only one who got this to pass, to find out later that what cause the 
> error had nothing to do with the message I displayed. Checking that something 
> dies is _not_ good enough. One should check more thorowly. Yes, I know I can 
> use throws_ok but why have dies_ok ?

Because you don't always know what the error message will be and its not always 
under your control.  Consider error messages that change with the locale.  Or 
for different versions of dependent software.  Is it worth the complicated test 
logic to cover all the error messages?  The false failures when it inevitably 
doesn't cover some case?  Sometimes it isn't.

And because, unlike some other languages that start with a letter P or J, Perl 
isn't about taking away a tool just because you might use it wrong.

FWIW I'd actually write...

  eval { $foo->method1 };
  isnt $@, '';

Its rare enough that I don't need a module to do that.  I'm sure you can find 
nearly that exact code around, there's some in the Perl core test suite.  But 
its nice to have the shorthand.


>   # Check that something did not die
>   lives_ok { $foo->method2 } 'expecting to live';
> 
> Is the above realy a test? Ok but testing what? why wouldn't we wrap all our 
> test in lives_ok? No, I don't think lives_ok makes any sense. I'd be very 
> happy to see real examples of lives_ok that add anything to a test suite.

Here's a situation I worked on just today, really.  I'm at a new contract and 
I'm faced with a test suite that has been failing for months.  Its day two and 
I don't understand the code base enough to fix the test.  I want to at least 
mark the existing tests TODO so I can at least see when new tests start failing 
and restore confidence in the test suite.

In one instance a function is dying because its being called wrong.  I can't 
just wrap it in a TODO test, I need it to not die.  Thus...

    TODO: {
        local $TODO = 'function_thats_dying() is being called wrong';
        lives_ok { function_thats_dying( @wrong_args ) };
    }

Again, what I actually did was use eval.

    TODO: {
        local $TODO = 'function_thats_dying() is being called wrong';
        eval{ function_thats_dying( @wrong_args) };
        is( $@, '' );
    }

Again, its nice to have the shorthand.


>   # Check that a test runs without an exception
>   lives_and { is $foo->method, 42 } 'method is 42';
> Isn't this equivalent to is($foo->method, 42 , 'method is 42') ? The test 
> framework will catch the error if any. It's just weird to attempt to catch 
> something when the expected result is to pass.

See above.


>   # all Test::Exceptions subroutines are guaranteed to preserve the state 
>   # of $@ so you can do things like this after throws_ok and dies_ok
>   like $@, 'what the stringified exception should look like';
> 
> This wouldn't be needed if dies_ok didn't exist.

throws_ok() has two tricks.  It can test $@ if its a certain class and it can 
test if $@ matches a regex.  That's too restrictive.  What if I want to test if 
$@ exactly matches a string?  Sure, I can do qr/\A\Q...\E\z/, but that's ugly 
and how many times will you use /^\Q...\E$/ or /\A\Q...\E\Z/ and get it 
slightly wrong?  What if it throws an exception object and I want to further 
examine that object?  Call methods on it?  After all, it went through the 
bother of throwing an object, I should at least have the decency of looking at 
it.

These features exist to allow you to use the Test::Exception functions and yet 
still do additional testing that Test::Exception normally doesn't allow you to. 
 Similar to the way Test::More provides ok().  There's better functions for 
most things, and they provide better diagnostics, but ok() can test *anything*.

Reply via email to