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

Hi Monks, I am new to this and looking into using Perl Test module to test some programs. What other ways can i rearranging this into a more consolidate suite? Would it be possible to include both test into one prog? I might have 30 test items to be tested and do not want to have 30 cmd(s). The program i have had about 30 parameters just like uname have about 10. uname -a uname -n uname -s uname -r- you get my point :) ++++++++++++++++++++++++++++++++++++
#!/usr/bin/perl use strict; use warnings; use Test::More tests => 6; use Test::Cmd; my $cmd = Test::Cmd->new( prog => '/bin/uname' ); is $cmd->run, 0, 'uname ran okay'; is $cmd->stdout, "Linux", 'Test uname match 1'; like $cmd->stdout, qr/Linux/, 'Found uname parameter Linux'; my $cmd2 = Test::Cmd->new( prog => '/bin/uname -n' ); is $cmd2->run, 0, 'uname ran okay'; is $cmd2->stdout, "Desktop1", 'Test Uname match with node'; like $cmd2->stdout, qr/Desktop/, 'Found uname with node name';
Thanks in advances, piew

Replies are listed 'Best First'.
Re: Better arranging Test Suite
by Corion (Patriarch) on Aug 12, 2007 at 20:56 UTC

    I often use a data-driven approach in such situations:

    You have three parameters for each program:

    1. The program and its path and command line
    2. The output of the command
    3. A regular expression that should match the output

    One of 2. and 3. seems superfluous - either you have a literal match or a regex, but it's unlikely you need both. But that's a different problem.

    My approach is to store all three items in a simple ASCII table and let the test driver run over that table:

    use strict; use Test::More; use Test::Cmd; my @tests = map { split /\|/, $_, 3 } <DATA>; close DATA; plan tests => @tests * 3; for (@tests) { my ($prog,$stdout,$stdout_re) = @$_; my $cmd = Test::Cmd->new( prog => $prog ); is $cmd->run, 0, ">>$prog<< ran okay"; is $cmd->stdout, $stdout, 'Output is OK'; like $cmd->stdout, qr/$stdout_re/, 'Found expected output'; }; __DATA__ /bin/uname|Linux|Linux /bin/uname -n|Desktop1|Desktop

    Update: andreas1234567 spotted a bug in the argument order to split, fixed

Re: Better arranging Test Suite
by xdg (Monsignor) on Aug 12, 2007 at 20:59 UTC

    I usually do this sort of things with a data structure of my tests and a simple loop with the repetitive test code. E.g.

    #!/usr/bin/perl use strict; use warnings; use Test::More; # no plan here -- plan later use Test::Cmd; my @cases = ( # label, args, exit, expected, regex [ "plain", "", 0, "Linux", "Linux" ], [ "with node", "-n", 0, "Desktop1", "Desktop" ], ); my $tests_per_case = 3; plan tests => $tests_per_case * @cases; for my $case ( @cases ) { my ($label, $args, $exit, $expected, $regex) = @$case; my $cmd = Test::Cmd->new( prog => "/bin/uname $args" ); is $cmd->run, $exit, '$label\: uname ran okay'; is $cmd->stdout, $expected, "$label\: Test uname $args"; like $cmd->stdout, qr/$regex/, "$label\: Found uname parameter '$r +egex'"; }

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      Thank you both. Both have better and cleaner approach.

        Corion's approach works well when the data is pretty static. I often wind up needing perl data structures as input to my case, so I specify my cases in code rather than in DATA. But both are the same basic approach.

        -xdg

        Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.