Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

How to share an object between test cases using Test::Harness

by psantann (Novice)
on Feb 25, 2011 at 02:39 UTC ( [id://890108]=perlquestion: print w/replies, xml ) Need Help??

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

Hello fellow monks,

I'm trying to create a cache of objects and have them shared between test files using Test::Harness, or more specifically, TAP::Parser. I see that I can pass cmdline like args using test_args but that does not work for an object. I even tried to use freeze/thaw but that doesn't work either, in fact since this object contains a TCP/IP socket I'm afraid any serialization solution might just not be appropriated.
What I have tried was to create the cache in a module that loads the test files and them refer to that cache from the test files. The trouble seems to be that each test file "uses" this module independently, instead of keeping whatever values where set by previous test file executions. My problem could maybe be summarized by the following code, in it, if I could get the value of $one to be updated from test file1 to test file2, then the test on file2 would not fail.


# harness.pl - Main Program
#!/usr/bin/perl use strict; use warnings; use TAP::Parser; use Tester; Tester::main();
# Tester.pm - Loads test cases
#!/usr/bin/perl use strict; use warnings; use TAP::Parser; package Tester; our $one = 1; sub main { my @test_files = qw( file1 file2 ); for my $file ( @test_files ) { my %args = ( source => $file, test_args => [ arg1 => 'arg1' ], # Not used for ilustr +ation only ); my $parser = TAP::Parser->new( \%args ); while ( my $result = $parser->next ) { print $result->as_string, "\n"; } } } sub get_one { return $one; } sub set_one { my $class = shift; $one = shift; } 1;
# file1 - First test case
#!/usr/bin/perl use strict; use warnings; use Test::More 'no_plan'; use Tester; Tester->set_one(1); my $one = Tester->get_one(); Tester->set_one(2); # Try to set this for the next test Test::More::is( $one, 1, 'One equals to one' );
# file2 - second test case (fails $one is reset to 1)
#!/usr/bin/perl use strict; use warnings; use Test::More 'no_plan'; use Tester; Tester->set_one(1); my $one = Tester->get_one(); Tester->set_one(2); # Try to set this for the next test Test::More::is( $one, 1, 'One equals to one' );

Replies are listed 'Best First'.
Re: How to share an object between test cases using Test::Harness
by ELISHEVA (Prior) on Feb 25, 2011 at 12:04 UTC

    Test::Harness isolates each test suite so you can be sure to have a clean starting environment for each test. If dump/load is not appropriate to your testing situation, as far as I know there isn't (and shouldn't) be a way to share objects between .t files.

    What I would recommend instead is rethinking your allocation of tests to files. Put any set-up/tear-down code for tests in a module, i.e. a .pm file. Include that file in your .t files using a use My::Testing::Library statement. This will reduce the length of both test1.t and test2.t (or whatever you call them). Next combine all tests that share a common object into a single test file.

    If you need to run only half the tests at any one time, use any arguments your harness will let you pass to tests to control which tests run. However, please note that some of the older implementations of Test::Harness and prove don't allow you to pass arguments to .t files. You can work around this by setting environment variables, though there might be portability issues involved if you go that route and your software will be distributed on platforms that are not available to you for portability testing. Whatever you do, command line arguments or environment variables, make sure you document them clearly in a place that is easy to find.

    To make sure your test plan counts don't get botched, use skip to skip any tests not appropriate to the current test selection. If you can count on a Perl 5.12 installation (or your installation sites are allowed to download the lastest version of Test::More) you can also avoid hard coded counts and use done_testing instead.

    If you are planning to distribute this module on CPAN [ and want older systems to be able to use your module ] you will need to be especially careful about backwards compatibility issues. For example, older systems have a version of Test::More that won't recognize done_testing and will not be able to pass your tests if you rely on that subroutine. Attempts to compensate for the limitations of older installations by writing your own test harness might also run into difficulties - see Re^9: Do Pure Perl CPAN packages really need to use ExtUtils::Command::MM? and replies for a discussion of some of the issues related to custom test harnesses under ExtUtils::MakeMaker and Module::Build. See also http://search.cpan.org/~evo/Class-MakeMethods-1.01/test.pl.

    I really wish I had a less complicated solution for you.

    Update: add bracketed clarification in next to last paragraph in response to anonymous monk below.

      If you are planning to distribute this module on CPAN you will need to be especially careful about backwards compatibility issues.

      This is not a requirement for publishing to CPAN

      Hi Elisheva, Thank you for this detailed response as well. Currently I'm doing something like that. I have a specific module that handles the object creation and it is called by the test cases. What I wanted to accomplish was that if there is already a connection to my end device and the object already holds all the data I need for further testing, I wanted to leverage this connection and all the existing data, instead of reestablishing the connection and resending setup messages for each test case. Of course each test file will have its share of messages/responses to send and process but there is a subset that is part of the setup that I wanted to avoid repeating. If not only for speed but also to simplify troubleshooting on the device side. Thanks for the tip on done_testing. It does not affect me too much in this case since I'm using TAP::Parser and TAP::Parser::Aggregator to collect my test results but is good to know.
        After testing a few serialization options including Data::Dumper, Storable and YAML. (Found an interesting article on these and others here:
        http://www252.pair.com/comdog/mastering_perl/Chapters/14.persistence.html)
        I came to the conclusion that the complexity of storing my connection data is not worth the effort ( ran into segmentation faults and other oddities).
        In the end I decided to implement Elisheva's suggestion and run the test cases in a unified form as a single file. That way caching an object became a breeze. Also, I found a way to keep the files separated by making them Perl modules with a single exportable sub that run all tests in that module. A separated file "uses" all the modules and keeps the "memory" of previous tests, and I pass that file to TAP::Parser. Something like this:
        # Main Program ... my $test_file = "MetaTester.pm"; my %args = ( source => $test_file ); my $parser = TAP::Parser->new( \%args ); while ( my $result = $parser->next ) { ... # Then in MetaTester.pm use Test1.pm; use Test2.pm; Test1::run_tests(); Test2::run_tests();
        Thanks again to all that responded.
Re: How to share an object between test cases using Test::Harness
by mellon85 (Monk) on Feb 25, 2011 at 05:00 UTC

    You just import the package Tester in 2 different files, there is no sharing of any kind of data.

    If you want a persistent object between test cases you need to save/load it in your test cases

      Hi, Thanks for you response! Yes, I think that might be the appropriated route for me. As I mentioned before, the trick here is to save the status of the network connection between each test file run. Does anyone have any module recommendations that would be appropriated to handle that?

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://890108]
Approved by ww
Front-paged by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (6)
As of 2024-04-23 07:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found