http://www.perlmonks.org?node_id=923392

chrestomanci has asked for the wisdom of the Perl Monks concerning the following question:

Greetings brothers.

I am currently writing a test suite for a DBIx::Class based project using Test::Class. I am having trouble with the order that Test::Class calls the startup methods I have defined.

package Test::Setup; use base 'Test::Class'; use Test::Most; # Pulls in strict, warnings, T::More, T::Exception +etc. use Schema; # The base of my DBIx::Class classes. sub db_connect : Test(startup) { my $self = shift; my $schema = Schema->connect('dbi:SQLite:dbname=:memory:'); $schema->deploy(); $self->{'schema'} = $schema; }; package Test::Schema::Result::Organisation; use base 'Test::Setup'; use Test::Most; # This does not work! # I expected it to get called after the parent class startup method, b +ut instead it gets called first, # before the startup method in Test::Setup so there is no DB connectio +n and the schema is not defined. # # Test::Schema::Result::Organisation::create_organisation sub create_organisation : Test(startup) { my $self = shift; my $schema = $self->{'schema'}; $self->{'Organisation'} = $schema->resultset('Organisation')->create +({ 'name' => 'BigCheeseIndustries', 'description' => 'Test Organisation for the test suite', }); return; };

In the example above, the create_organisation method gets called before the db_connect method that it depends on. I had expected Test::Class to respect the inheritance order of my test classes, and call the parent startup methods before the children, but that does not appear to be the case.

I have read in the Test::Class docs, that startup methods are run in alphabetical order, and I am able to fix the order by prefixing the method names with A_, B_ etc, but this feels like a crude hack. Is there a smarter way?

Replies are listed 'Best First'.
Re: Order of startup methods with Test::Class
by Old_Gray_Bear (Bishop) on Aug 31, 2011 at 11:41 UTC
    If you need to have the start up methods run in a specific order, something is wrong with your analysis of the problem.

    That said, change your naming convention from 'sub name_that_makes_sense{}' to 'sub startxxx_name_that_makes_sense {}' and replace the xxx with the order of starting number (000, 001, ... , 998, 999). (But I'd go back to the problem analysis and ask "Why are things order-dependent? If A simply MUST come before B, then why are they in different setup-routines?")

    ----
    I Go Back to Sleep, Now.

    OGB

Re: Order of startup methods with Test::Class
by Ovid (Cardinal) on Oct 09, 2011 at 15:02 UTC

    This is a common anti-pattern I see in Test::Class code. If you have a subclass, you should view this as a more specific instance of your parent class. Your startup/setup/teardown/shutdown methods (which I refer to as "test control methods") shouldn't rely on a prefix hack, as you rightly pointed out. Instead, you override them and your subclass calls the parent class's method as appropriate:

    sub setup : Tests(setup) { my $test = shift; $test->SUPER::setup; # my setup code here }

    With this approach, you have complete control over the order of how things run and you don't have to worry about prefixes.

    You might want to read my tutorial on Test::Class, in particular the test control methods section.

      Ovid++

      Thank you, that was the answer I was looking for.

      All I have to do is name all my setup methods the same, and subclass where appropriate.

        Happy to have helped. By the way, I noticed you're using my Test::Most module. Since you're also using Test::Class, you might also find my Test::Class::Most module handy.