Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

Ovid
  (email not shown publicly)
http://publius-ovidius.livejournal.com/
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Wednesday April 23, 2008
04:51 AM

Test::Class Recipe: Safe Fixture Methods

[ #36226 ]

I have written an article on Test::Class and really need to get around to finalizing and publishing it, but in the meantime, I think some Test::Class "recipes" are in order.

Problem: Your child's setup method is firing before the parent's setup method.

Solution: Give them the same name and use SUPER.

Explanation: In Test::Class, you have methods I think of as "fixture" methods, though that's not quite true and a better name is welcome. These methods are for:

startup: executes before the test class runs.
Example: create the database and connect.
shutdown: executes when the test class ends.
Example: drop the database and disconnect.
setup: executes before each test method.
Example: add test data.
teardown: executes after each test method.
Example: clear test data.

The problem is when you have a subclass. Since test methods run in alphabetic order, every class with "fixture" methods must know the case of complementary fixture methods in parent classes or child classes in order to ensure that they get fired in the right order. If you have this, your code will fail.

sub Parent::connect_to_db : Tests(startup) {
    my $test = shift;
    $test->dbh(connect());
}

# inherits from Parent
sub Child::begin_transaction : Tests(startup) {
    my $test = shift;

    # This fails because 'b' is run before 'c' (first letter of
    # method names) and dbh() is not yet defined
    my $dbh  = $test->dbh;
    ...
}

We can avoid this by naming all of these methods after the phase in which they get handled.

sub Parent::startup : Tests(startup) {
    my $test = shift;
    $test->dbh(connect());
}

# inherits from Parent
sub Child::startup : Tests(startup) {
    my $test = shift;
    $test->SUPER::startup;
    my $dbh  = $test->dbh;
    ...
}

In startup and setup, the SUPER call should happen at the start of the method. In teardown and shutdown, the SUPER call should happen at the end of the method.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • Ovid wrote:

    We can avoid this by naming all of these methods after the phase in which they get handled.

            sub Parent::setup : Tests(startup) {


    I think you meant to name that method (and the subclass method) startup