[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]

request does_ok() as per isa_ok() in Test::More/etc



Hello,

I would like to request a simple new feature for the next CPAN release of
Test::More/Builder/Simple/etc (and by extension the next Perl 5 core since
those are bundled with it).

Please add a clone of the isa_ok() routine that has the name does_ok() and
that tests its main subject argument using ->does() rather than ->isa();
its second main parameter would be named $role rather than $class.

The functionality of the new routine would be like the Perl 6 Test.pm's
does_ok() routine, which has no counterpart in the current Test::More.

The rationale for having this now in Perl 5 is related to the greatly
increasing popularity of Moose, as well as other modules, that allow you to
introspect whether an object consumes a role.

For anyone using Moose roles these days, it is common for role consumption
to replace normal class inheritance, and often tests for Moose-using code
want to test that some code produced an object that consumes a role, rather
than that inherits a class.  For example we just want to test that an
object will provide an interface, but the actual class hierarchy doesn't
matter.

The current isa_ok() of Test::More does not test whether an object consumes
a role, and I don't see anything else in Test::More that will do the job
cleanly.

So far to work around the limitation, my Test::More-using
Muldis::Rosetta::Validator module on CPAN includes its own copy of isa_ok()
from 0.72 minimally modified as I mentioned (I have pasted a copy at the
end of this email as well, as a quasi-patch you can use).

But my copy is an inelegant solution compared to Test::More supporting the
functionality natively, especially since it is so similar to functionality
that Test::More already has.

I'll note that adding this feature to Test::More is not likely adding any
external dependencies, since it mainly just needs to test for provision of,
and then invoke, a does() method or routine, same as it now checks for isa().

Thank you in advance for this consideration.

-- Darren Duncan

--------------

# Modified clone of isa_ok from Test::More 0.72 (what Perl 5.10.0 bundles),
# since we actually want to test with does() rather than isa();
# it is identical to the original save the s/isa/does/g and s/class/role/g;
# this will probably be replaced later with something simple.
# Note: The internals of Test::More/etc were different at least as recently
# as version 0.62 (what Perl 5.8.8 bundles); 0.62 is incompat with this.

sub does_ok ($$;$) {
     my($object, $role, $obj_name) = @_;
     my $tb = Test::More->builder;
     my $diag;
     $obj_name = 'The object' unless defined $obj_name;
     my $name = "$obj_name does $role";
     if( !defined $object ) {
         $diag = "$obj_name isn't defined";
     }
     elsif( !ref $object ) {
         $diag = "$obj_name isn't a reference";
     }
     else {
         # We can't use UNIVERSAL::does because we want to honor does()
overrides
         my($rslt, $error) = $tb->_try(sub { $object->does($role) });
         if( $error ) {
             if( $error =~ /^Can't call method "does" on unblessed
reference/ ) {
                 # Its an unblessed reference
                 if( !UNIVERSAL::does($object, $role) ) {
                     my $ref = ref $object;
                     $diag = "$obj_name isn't a '$role' it's a '$ref'";
                 }
             } else {
                 die <<WHOA;
WHOA! I tried to call ->does on your object and got some weird error.
Here's the error.
$error
WHOA
             }
         }
         elsif( !$rslt ) {
             my $ref = ref $object;
             $diag = "$obj_name isn't a '$role' it's a '$ref'";
         }
     }
     my $ok;
     if( $diag ) {
         $ok = $tb->ok( 0, $name );
         $tb->diag("    $diag\n");
     }
     else {
         $ok = $tb->ok( 1, $name );
     }
     return $ok;
}




Follow-Ups from:
Matt S Trout <dbix-class@trout.me.uk>

[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]