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

Dear Monks,

for the moment being I do my testing of complete Perl scripts like this:
my( $ok, $failure ) = ( 0, 0 ); ... system( "", $par1 ) ); $? ? $failure++ : $ok++; system( "", $par2 ); $? ? $failure++ : $ok++; ...

What I'm looking for is a module to assist the tiresome procedure plus give me the usual support of plans, expected failures, todos, etc.

Has anybody a recommendation which Test module best fits my need?

Thanks, Axel

Replies are listed 'Best First'.
Re: Test module to assist sytem()
by ph0enix (Friar) on Nov 29, 2002 at 12:27 UTC

    I have only one note - use $? >> 8 instead of $? for testing return code from system call.

Re: Test module to assist sytem()
by axelrose (Scribe) on Nov 29, 2002 at 14:47 UTC
    #!/usr/bin/perl -w use strict; use Test::Simple tests => 3; systest( 0, ("who") ); systest( 0, ("who", "am", "i") ); systest( 1, ("bash", "-c", "exit 1") ); sub systest { my $expected = shift; my @cmd = @_; system @cmd; my $sysres = $? >> 8; ok( $sysres == $expected, "'@cmd' returned $sysres" ); }
    The disadvantage here is the mixed output from the test script and the system() calls. I cannot simply add ">/dev/null" to @cmd. My real script parameters rely on not using a Shell for system().

      You want to use Test::Builder->is_num() rather than wrapping Test::Simple's ok(). You get the benefit of is() and failure diagnostics will point to the line where systest() was called, not the line where ok() was used inside systest().

      As for the problem of supressing/trapping the STDOUT/STDERR from system(), just redirect them inside perl. There's several ways to do it. Dup & close to supress. Tie or redirect to a temp file to capture. An exercise which I will leave for the reader. :)

      use Test::Simple tests => 3; use Test::Builder; my $tb = Test::Builder->new; systest( 0, ("who") ); systest( 0, ("who", "am", "i") ); systest( 1, ("bash", "-c", "exit 1") ); sub systest { my $expected = shift; my @cmd = @_; system @cmd; my $sysres = $? >> 8; $tb->is_num( $sysres, $expected, "'@cmd'" ); }
Re: Test module to assist sytem()
by Anonymous Monk on Nov 29, 2002 at 22:03 UTC

    I just noticed Test::Cmd on CPAN. It looks ludicrously powerful. Possibly overkill for most people, but you could probably wrap it.

    There's also some work I did for the Good Folks at Mitel Network Server Solutions (if that's a mouthful, just say "E-Smith") which is fortunately GPL'd. If you can get a copy of their e-smith-test.srpm you'll find the esmith::TestUtils library with a little thing called simulate_perl_program(). It will "run" a perl script but not as a seperate process.

    This is for the case where you have a perl script you wish to test but have to change something about it in order to make it testable. For example, maybe it uses a database, you want it to use a test database but there's no easy way to change where it connects to. You can wrap DBI::connect() to alter the database connection, then call simulate_perl_program(). The program's code calls DBI->connect, it hits your wrapper, swaps out the hardcoded name with the name of the test database and passes it through to the real DBI test.

    Something like:

    use DBI; { my $real_connect = DBI->can('connect'); no warnings 'redefine'; local *DBI::connect = sub { my($self, $ds, $user, $pass, $attr) = @_; $ds =~ s/yourdb/testdb/; $self->$real_connect($ds, $user, $pass, $attr); }; my $exit = simulate_perl_program('yourprogram.plx', @args); }

    Additionally, if you're using Test::Inline, $_STDOUT_ and $_STDERR_ from simulate_perl_program() are simply trapped like always.

    If someone has the tuits, it would be nice to see this taken out of e-smith-test and put on CPAN. I've temporarily mirrored ESmith::TestUtils

      Damn those cookies. That's all me above.