Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Re: Test::Class & self-shunt pattern

by pdcawley (Hermit)
on Jan 13, 2003 at 07:14 UTC ( [id://226412]=note: print w/replies, xml ) Need Help??


in reply to Test::Class & self-shunt pattern
in thread Documenting Methods/Subs

Cute trick. It's actually something I'd considered but rejected (but I would say that wouldn't I?), but your wrapper is very neat.

The problem with it, as I see it is that, with optimisitic typing (ie, just passing in $self), you get an immediate failure if the object under test calls an unexpected method simply because you haven't implemented it. With a localized @ISA, Logger's methods becomes callable and an unexpected method call could get dispatched to real code (and you can't be sure that that would throw an exception.

If Params::Validate does the right thing ($obj->isa('foo'), not UNIVERSAL::isa($obj, 'foo')) then you could always do

sub _do_as (&$) { my($block, $fake_class) = @_; local *Object::Test::isa = sub { my($self, $target_class) = @_; return $target_class eq $fake_class || $self->SUPER::isa($target_class); }; $block->(); }
If the validater calls UNIVERSAL::isa, you could override that instead, but it would be rather more awkward. And it's all a good deal more awkward than just chucking the test object in without adornment.

This really comes down to how much value you see in the strict typing of variables. Personally I am unconvinced by it. I'd prefer to see a good test suite (and Smalltalk style method selectors, but they're rather harder to come by in Perl. Smalltalk method selectors are great though. They give you lots more naming opportunities, your 'new' method would become

newWithLogger: aLogStream ^ self new setLogger: aLogStream
which isn't necessarily the most convincing of arguments, but believe me it's great with more complex method signatures...)

Replies are listed 'Best First'.
Re^2: Test::Class & self-shunt pattern
by adrianh (Chancellor) on Jan 13, 2003 at 10:40 UTC

    The problem with it, as I see it is that, with optimisitic typing (ie, just passing in $self), you get an immediate failure if the object under test calls an unexpected method simply because you haven't implemented it.

    Fair point. Although in some circumstances that could be what you want :-)

    Instead of replacing stuff I sometimes just add instrumentation with something like Hook::LexWrap - handy when retrofitting tests onto tightly coupled code.

    This really comes down to how much value you see in the strict typing of variables.

    Well, all the ways of doing it in perl suck in one way or another so I don't often use it, but it's nice if done right (Eiffel springs to mind).

    Method selecters are cool, and interfaces would be yet another solution.

    Maybe in perl6 :-)

      Hook::LexWrap is very cool certainly. I'd not thought of using it for hammering tests into tightly coupled code, but now you mention it, it's a bloody good idea.
      Method selecters are cool, and interfaces would be yet another solution.
      I happen to know there's someone working on method selectors in Perl 5. And, despite having written the Perl 6 RFC calling for Interface support, I'm becoming less and less convinced by them. Again, in a self shunt context, if you declare that a test case implements the 'foo' interface then you're obliged to implement all the methods in the 'foo' signature if you want the thing to compile, which can be somewhat painful, especially when you're adding the nth interface to your test class.

        Hook::LexWrap is very cool certainly. I'd not thought of using it for hammering tests into tightly coupled code, but now you mention it, it's a bloody good idea.

        I love Hook::LexWrap. It allows you to do so many evil things :-)

        despite having written the Perl 6 RFC calling for Interface support, I'm becoming less and less convinced by them

        I'm not too fond of interfaces either. I think they're the wrong solution to the problems of C++'s multiple inheritance implementation.

        However, couldn't you just generate the missing methods at compile time (assuming there is some kind of introspection on your classes interfaces)?

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (6)
As of 2024-03-28 21:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found