Extensive POE Testing PT. 3 - Testing, Sequence Ordered

xsawyerx on 2009-10-11T09:42:27

My last post went over the idea of ordered tests, in which we run events in a certain order. It's a simple concept, it's easy to test and it's very nifty.

However, it fails to cover some more advanced grounds, specifically the idea of multiple runtimes of a session or event, in which we can result in a race condition where two or more instances of the event will try to fire first and we aren't exactly sure which will come first. One could stumble over an if() that will take it a little bit more while the other might handle an unexpected delay because of its flow.

Still, the point to make is that usually in such situations we don't really care what was the numbered order of the events, we care about the preceeding order of the events. Meaning, the sequence of events.

Here is an example:

package MyPackage;
use MooseX::POE;

has 'num' => ( is => 'ro', isa => 'Int', default => 0 );

sub START { # in MX::POE, this is mapped to _start
    $_[KERNEL]->yield('first');
}

event 'first' => sub {
    if ( $_[OBJECT]->num == 7 ) {
        # lucky number slevin
        $_[KERNEL]->yield('long_taking_event');
    }

    $_[KERNEL]->yield('second');
};

event 'second' => sub {
    print "reached second!\n";
};

event 'long_taking_event' => sub {
    print "reached long taking event!\n";
};

package main;
MyPackage->new( num => rand(10) ) for 1 .. 5;

In this example, we aren't exactly sure if num will be 7 or not, and thus we aren't sure if long_taking_event will even be called. Besides, we're running each event more than once so the order function with the static number of running order of the events cannot even be applied here.

Interestingly enough, we can stipulate that we do know first is suppose to run only after START. This might seem a bit given, but maybe we've made an error in the code and run first directly? How about knowing that long_taking_event and second can only be run after first? That's pretty good to know. If we run the program and it will see that second ran before first, we know we've made a mistake!

That's what I call sequenced-ordered tests or event-dependency order. It's when the order isn't conclusive, but the sequence of events is. Right now my (yet unnamed and unpublished) framework supports that in a very simple form:

with 'POE::Test::Simple'; # running title

has '+seq_ordering' => ( default => sub { {
    'first'            => [ 'START'          ],
    'second'           => [ 'START', 'first' ],
    'long_taking_event => [ 'START', 'first' ],
} } );

# then each event/sub called can register itself with the framework
event 'second' => sub {
    $_[OBJECT]->seq_order('second');
};

Right now I'm working on making this implicit so it's not required to run at all in order for the testing to run. Much help on this came from mst, doy and other great people at #moose. Thanks guys!

Again, thinking about what this still misses:

how many times each event ran?
We have no counting of this, so the next post will cover event counting, which is exactly it. Meanwhile, if you feel like pitching ideas for the framework module name, I'd appreciate it.