Ovid has asked for the wisdom of the Perl Monks concerning the following question:
Summary: Test::Class setup and teardown methods should call their SUPER equivalents, if present.
In Test::Class, aside from marking methods as tests, you can also mark them as startup, setup, teardwown, and shutdown. For the sake of this question, I'll just focus on the setup and teardown methods. These run before and after every test method, respectively. You might see something like this:
sub pre_test : Test(setup) { # add objects to the database } sub get_objects : Tests { # get the objects and test 'em } sub post_test : Test(teardown) { # clean the database }
This is fine, but it doesn't work as well when you're inheriting tests (something to avoid, but it happens). Your derived classes really want to call the parent classes' setup methods but this doesn't happen automatically.
Here's how to replicate this:
The base class:
package TestBase; use base 'Test::Class'; INIT { Test::Class->runtests } 1;
A parent class with tests:
package Foo; use Test::More; use lib '.'; use base 'TestBase'; sub setup : Tests(setup => 1) { ok 1, 'Foo: should be called first'; } sub some_test : Tests(1) { ok 1, 'Foo: some test'; } sub not_overridden : Tests(1) { ok 1, "Let's hope this isn't dependent on Foo's setup method"; } 1;
And a subclass:
package Bar; use Test::More; use lib '.'; use base 'Foo'; sub setup : Tests(setup => 1) { ok 1, 'Bar: should be called second'; } sub some_test : Tests(1) { ok 1, 'Bar: some test'; } 1;
If you execute the subclass, Bar, you get the following:
1..8 ok 1 - Bar: should be called second ok 2 - Let's hope this isn't dependent on Foo's setup method ok 3 - Bar: should be called second ok 4 - Bar: some test ok 5 - Foo: should be called first ok 6 - Let's hope this isn't dependent on Foo's setup method ok 7 - Foo: should be called first ok 8 - Foo: some test ok All tests successful. Files=1, Tests=8, 0 wallclock secs ( 0.11 cusr + 0.02 csys = 0.12 C +PU)
What's happening is that every test class is loaded and the Test::Class->runtests in the base class is running every test class but we can see that when Bar is run, Foo's setup method is not called and this seems like a mistake since the parent setup methods are often setting up things that their methods require. The solution almost looks like:
sub setup : Tests(setup => 1) { my $test = shift; $test->SUPER::setup; ok 1, 'Bar: should be called second'; }
That doesn't work because I've declared a test count for each setup method and that throws my test count off (running two tests instead of one). Does this look like a bug in Test::Class or have I missed something here?
Update: you can get the superclass setup methods to be called if if you don't override them by providing a subclass method of the same name, but then they're called in alphabetical order. As I've painfully discovered, that breaks things if your subclass setup method relies on something your superclass setup method creates.
Cheers,
Ovid
New address of my CGI Course.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Test::Class and setup methods
by adrianh (Chancellor) on Mar 14, 2007 at 12:11 UTC | |
by Ovid (Cardinal) on Mar 14, 2007 at 12:25 UTC | |
by adrianh (Chancellor) on Mar 14, 2007 at 12:44 UTC |