Hi,

I've encountered a little problem using dies-ok() from the Test module;

The case was that I made an error within the block used as the first argument to dies-ok. In that particular case the perl6 compiler hurled an exception and dies-ok accepted it as an ok action which was not ok because the real test was not performed.

I have reverted to the try/catch methods I used before because I can then test the
exception object in $_ for its type and message.

Perhaps dies-ok could be extended to do these test for me, testing any field in the object available. Something like; dies-ok {... test ... }, '...description...', :name<...exception object name...>, :message<...>;

where :name tests the exception object for its name(.^name) and :message tests the payload of the object by calling the message method when available. Maybe some other less common methods of the exception object can be tested this way. The named attributes can be optional to revert to old behaviour.

The code below can also be found at https://gist.github.com/MARTIMM/747ccf562b18e42235efe7623673978d

use v6;
use Test;
#------------------------------------------------------------------------------
d-ok( {die 'oh oh 0';}, 'oh oh 0');
d-ok( {die 'oh oh 1';}, 'oh oh 1', :name<X::AdHoc>);
d-ok( {die 'oh oh 2';}, 'oh oh 2', :message<oh oh 2>);
d-ok( {die 'oh oh 3';}, 'oh oh 3', :name<X::AdHoc>, :message<oh oh 3> );
d-ok( {die 'oh oh 4';}, 'oh oh 4', :name<X::AdHoc>, :message(/ '4' $/) );

# Dies without knowing that the method Lisp does not exist!
d-ok( {'oh oh 5'.split('o').Lisp;}, 'oh oh 5');

# When :message or :name is used the result would fail showing a modified 
description
d-ok( {'oh oh 6'.split('o').Lisp;}, 'oh oh 6', :name<X::AdHoc>);

# Other examples with mistakes in what the name or messages should be
d-ok( {die 'oh oh 7';}, 'oh oh 7', :name<XX::AdHoc>);
d-ok( {die 'oh oh 8';}, 'oh oh 8', :message<ohhh>);
d-ok( {die 'oh oh 9';}, 'oh oh 9', :name<X::AdHoc>, :message(/ '4' $/) );

#------------------------------------------------------------------------------
# alternative dies-ok. Returns a list which must be flattened to be used with 
(n)ok.
# :message can be a string or regex. name and message are optional.
sub d-ok ( Code:D $code, Str $description is copy, Str :$name, :$message ) {

  my Bool $dies-ok = False;

  try {
    $code();

    CATCH {
      default {
        $dies-ok = True;

        if ? $name {
          $dies-ok = .^name eq $name;
          $description = .^name ~ ': ' ~ .message unless $dies-ok;
        }

        if $dies-ok and $message ~~ Str and ? $message {
          $dies-ok = .message() eq $message;
          $description = .^name ~ ': ' ~ .message unless $dies-ok;
        }

        if $dies-ok and $message ~~ Regex {
          $dies-ok = ?(.message() ~~ $message);
          $description = .^name ~ ': ' ~ .message unless $dies-ok;
        }
      }
    }
  }

  ok $dies-ok, $description;
}

#------------------------------------------------------------------------------
done-testing;


Giving the following results;

prove6 -v t/dies-ok.t
t/dies-ok.t ..
ok 1 - oh oh 0
ok 2 - oh oh 1
ok 3 - oh oh 2
ok 4 - oh oh 3
ok 5 - oh oh 4
ok 6 - oh oh 5
not ok 7 - X::Method::NotFound: No such method 'Lisp' for invocant of type 'Seq'

# Failed test 'X::Method::NotFound: No such method 'Lisp' for invocant of type 
'Seq''
# at t/100-fromfile.t line 90
not ok 8 - X::AdHoc: oh oh 7

# Failed test 'X::AdHoc: oh oh 7'
# at t/100-fromfile.t line 90
not ok 9 - X::AdHoc: oh oh 8

# Failed test 'X::AdHoc: oh oh 8'
# at t/100-fromfile.t line 90
not ok 10 - X::AdHoc: oh oh 9

# Failed test 'X::AdHoc: oh oh 9'
# at t/100-fromfile.t line 90
1..10
# Looks like you failed 4 tests of 10
Dubious, test returned 4 (wstat 1024, 0x400)
Failed 4/10 subtests

Test Summary Report
-------------------
t/dies-ok.t (Wstat: 1024 Tests: 10 Failed: 4)
  Failed tests:  7-10
  Non-zero exit status: 4
Files=1, Tests=10,  0 wallclock secs ( 0.02 usr  0.00 sys +  0.30 cusr  0.02 
csys =  0.34 CPU)
Result: FAIL

The last 4 descriptions are changed by the sub to make it clear that the exception name and/or message are different. Note that test 6 is successful even when something different is meant, test 7 shows that the method was non existent. This could have been a typo which would otherwise go undetected.

Regards,
Marcel


Reply via email to