Extensive POE Testing PT. 2 - Testing, Ordered

xsawyerx on 2009-10-09T14:32:50

A special thanks goes here to Adam Kennedy for sending me on this path and giving me ideas. Adam, I wanted to thank you personally but couldn't catch you on IRC, so thanks! :)

I tried to cover in my last post the basic guidelines I have for testing in POE. Testing in POE is different since we want to test a flow and not just subroutines. This time I want to try go over the first type of tests that I find necessary. It's called ordered tests - at least that's how I call it.

This method was first hinted at me by the great Adam Kennedy who used it in his POE::Declare module. Basically it describes the following scenario: I have a POE::Session event flow and I want to make sure that every event is run at the specific order.

package MyPackage;
use MooseX::POE;
use Test::More;

# this is taken from POE::Declare's t/04-stop.t
my $order = 0;
sub order {
    my $position = shift;
    my $message  = shift;
    is( $order++, $position, "$message ($position)" );
}

# then we can do this (written in MX::POE)
event 'eg' => sub {
    order( 0, 'Started eg event' );
};

Now, each event could run this subroutine with a number indicating the order of this event in our overall flow of the session. Here, for example, with the order( 0, 'event name' ) code if any event is running at a time that wasn't meant for it, it will fail.

However, it has a few disadvantages:

  • If any of the events repeat, it creates a problem. You'll have to set up a system to check which iteration of the event it is and execute the correct order()
  • What if you're yelding the kernel for two events and you aren't sure which one will run first?
  • What if it doesn't matter which one will run first?
  • What about running two sessions of the same object? It has the exact same events, with the exact same code. It will fail for sure.

My suggestion: allow a test that checks for event dependency. Instead of saying "this runs first", you could say "this runs ONLY after that" and "this - this runs only after these two". That would allow to have an order based on a sequence of events. Each event can only come after different events.

This is what the next post will discuss.


Single sequential run is what it's for

Alias on 2009-10-12T01:09:58

The reason I prefer my syntax to your dependency based on is that mine is easier to write and maintain, or so I find.

Of course, I completely acknowledge that it is intended for simple situations where the order is easily knowable.

Re:Single sequential run is what it's for

xsawyerx on 2009-10-12T06:50:17

Actually, my framework supports this specific type of tests and it looks very similar to the way you do it:

use MooseX::POE;
with 'POE::Test::Simple'; # again, working title
event 'next' => sub {
    $_[OBJECT]->order( 2, 'Running next' );
};

Only difference is mine is a Moose role that adds the order as a method of the session object. I started by implementing your method as a role and then noticed I need more options so I added more bells and whistles (which I'm now writing about).

However, I'm working on removing the necessity of this method (and hopefully the others) by automatically hooking up to events from the metaclass. All the numbering and test logic could be put in an overridden attribute. Rough example available on PT 3.