Re: dies-ok can return ok on everything dying

2017-04-18 Thread Timo Paulssen
You will be delighted to learn of the existence of the "throws-like"
subroutine in rakudo's Test.pm

There's also lots and lots of examples for its usage (and its power!) in
perl6/roast.

HTH
  - Timo


dies-ok can return ok on everything dying

2017-04-18 Thread mt1957

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);
d-ok( {die 'oh oh 2';}, 'oh oh 2', :message);
d-ok( {die 'oh oh 3';}, 'oh oh 3', :name, :message );
d-ok( {die 'oh oh 4';}, 'oh oh 4', :name, :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);

# Other examples with mistakes in what the name or messages should be
d-ok( {die 'oh oh 7';}, 'oh oh 7', :name);
d-ok( {die 'oh oh 8';}, 'oh oh 8', :message);
d-ok( {die 'oh oh 9';}, 'oh oh 9', :name, :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