Creating Test Fixtures

     

Imagine writing tests for your car. If you turn the wheel, do the tires turn left? What about right? If you hit the brakes, do the rear lights light up? Of course, before you can perform any of these tests, you need to open the door, sit in the driver's seat, put on the seat belt, and start the car. When you're done, you must stop the car, unbuckle, and disembark. What a pain it would be to perform each step for each individual test ”you'd have to get in and start the car three times!

It would be much easier if, before each test, your car arrived fully prepared and then magically transported you to the driver's seat, buckled you in, and fastened your crash helmet securely. This is exactly what fixtures are: parts of an environment created before tests run and removed after the tests finish.

This lab shows how to create fixtures for your tests using setup and teardown methods , which eliminates duplication and makes your test code more sane.

How do I do that?

Copy the Queue module and queue.t test file from "Writing Test Cases." However, the test module needs to change slightly. The new Queue::Test needs a new method, setup_queues( ) , to create a test fixture for the other test methods to use.

Save the following code as Queue/Test.pm :

 package Queue::Test;          use base 'Test::Class';          use Queue;     use Test::More;          sub setup_queues : Test( setup => 2 )     {         my ($self) = @_;              $self->{empty}    = Queue->new(  );         $self->{twoitems} = Queue->new(qw( howdy bonjour ));              isa_ok( $self->{$_}, 'Queue' ) for qw( empty twoitems );     }          sub size : Test(2)     {         my ($self) = @_;         is( $self->{empty}->size(  ),    0, 'an empty queue'             );         is( $self->{twoitems}->size(  ), 2, 'a queue with some elements' );     }          sub enqueue : Test(1)     {         my ($self) = @_;         $self->{twoitems}->enqueue($_) for qw( ciao yo );         is( $self->{twoitems}->size(  ), 4, 'queue is now larger' );     }          sub dequeue : Test(3)     {         my ($self) = @_;              is( $self->{empty}->dequeue(  ),    undef,     'empty queue' );              is( $self->{twoitems}->dequeue(  ), 'howdy',   'first item'  );         is( $self->{twoitems}->dequeue(  ), 'bonjour', 'second item' );     }          1; 

Run queue.t verbosely with prove :

 $  prove -v queue.t  queue....#     # Queue::Test->dequeue     1..12     ok 1 - The object isa Queue     ok 2 - empty queue     ok 3 - queue is now larger     ok 4 - first item     ok 5 - second item     ok 6 - queue is now smaller     #     # Queue::Test->enqueue     ok 7 - The object isa Queue     ok 8 - queue is now larger     #     # Queue::Test->size     ok 9 - The object isa Queue     ok 10 - an empty queue     ok 11 - The object isa Queue     ok 12 - a queue with some elements     ok     All tests successful.     Files=1, Tests=12,  0 wallclock secs ( 0.16 cusr +  0.03 csys =  0.19 CPU) 

What just happened ?

Every test method receives a hash reference as its first argument. This is the test object, and it exists to pass data from the fixtures to the tests. Feel free to add whatever you want to it.

Notice the output of prove -v ? There are a total of six isa checks, yet setup_queues( ) is the only method that calls isa_ok( ) , and it does so only twice. What happened? setup_queues( ) has the attribute Test(setup=> 2) .


Note: Test(setup)is the same as Test(setup =>0). The same goes for the teardown, startup, and shutdown attributes. It never hurts to be verbose, though .

The setup_queues( ) method prepares and checks the type of two Queue objects that all of the test methods use. Test::Class calls setup_queue( ) before each test method, so it runs three times in this test file. Each test method receives two fresh Queue objects in the test object. This simplifies the testing code by eliminating duplicate code, making it easier to add new tests.

What about...

Q:

What if I need to clean up the fixture after each test?

A:

Use a teardown method by creating a new method with the attribute Test(teardown => n ) . Teardown methods run after each test method.

Q:

Is it possible to have setup and teardown methods for the entire class?

A:

Sure! Test::Class calls these startup and shutdown methods. Declare them with the attributes Test(startup => n ) and Test(shutdown => n ), respectively. Each startup and shutdown method runs only once per test file. It receives the test object as the first argument, just like the other test methods.

Because startup methods run only once at the beginning of the test, they do not have the chance to reinitialize whatever they store in the test object as setup methods do.



Perl Testing. A Developer's Notebook
Perl Testing: A Developers Notebook
ISBN: 0596100922
EAN: 2147483647
Year: 2003
Pages: 107

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net