Unit testing and integration in perl with Test :: More - how to capture the exit call?

I have this script that converts a file from csv split into a constrained pipe (csv2pipe.pl).
The pipe delimited file is then loaded into the database.
I'm trying to run unit testing for it (csv2pipe_unit_test.pl with a test call like (main () ...).
The sub main () function in csv2pipe.pl has a call to exit if there is no given parameter.
Unfortunately, it is impossible to complete the exit call in test call so the test program just exits.
I can't do eval {code}. It doesn't catch the exit call. It will catch death and any errors, but not quit.
Same with the Capture :: Tiny package from CPAN. It doesn't catches the exit call.
Any ideas on how to test this main () call and exit call to exit?

File: csv2pipe.pl

#!/bin/perl
use strict;
use Getopt::Std;

#--------------------------
# all work done in main sub
#--------------------------
unless (caller) { main(); exit; }

sub main {
    printf( "START---$0---%s---\n", scalar( localtime(time) ) );

    if ( scalar(@ARGV) < 4 ) {
        print "Usage: $0 -i file.csv -o file.pipe\n";
        exit;
    }

    my %options = ();
    getopts( "i:o:", \%options );
    my $file_out = $options{o} or die "Missing -o param";
    my $file_inp = $options{i} or die "Missing -i param";

    if ( !-f $file_inp ) {
        die "Could not find file to parse ($file_inp)\n";
    }

    my $row_ctr = 0;
    open( FH_inp, "<$file_inp" ) or die "Could not open file: $file_inp";
    open( FH_out, ">$file_out" ) or die "Could not open file: $file_out";

    my ( $str, $ret );
    foreach $str (<FH_inp>) {
        $row_ctr++;
        #print "str=$str";
        $ret = csv2pipe($str);
        #print "ret=$ret";
        print FH_out $ret;
    }

    close(FH_inp);
    close(FH_out);
    print "Processed $row_ctr rows\n";

    printf( "END---$0---%s---\n", scalar( localtime(time) ) );
    printf( "Program Run Time: %s second(s).\n", ( time - $^T ) );
}

# convert csv to pipe
sub csv2pipe {
    my $str = shift;
    return undef if !defined $str;
    #print ''.(caller(0))[3]."\n";
    $str =~ s/,/|/g;
    if ( $str =~ /"/ ) {
        while ( $str =~ /".*?"/ ) {
            my $beg   = $`;
            my $match = $&;
            my $end   = $';
            $match =~ s/"//g;
            $match =~ s/\|/,/g;
            $str = $beg . $match . $end;
        }
    } elsif ( $str =~ /'/ ) {
        while ( $str =~ /'.*?'/ ) {
            my $beg   = $`;
            my $match = $&;
            my $end   = $';
            $match =~ s/'//g;
            $match =~ s/\|/,/g;
            $str = $beg . $match . $end;
        }
    }
    return $str;
}

      

File: csv2pipe_unit_test.pl

#!/bin/perl
use strict;
use warnings;
use Test::More;

# enter main test loop
run_tests();
exit;

sub run_tests {
    printf( "START---$0---%s---\n", scalar( localtime(time) ) );

    require_ok "csv2pipe.pl";

    ok( csv2pipe('') eq '',                                 'test empty string' );
    ok( csv2pipe('a') eq 'a',                               'test one char' );
    ok( csv2pipe('a,b') eq 'a|b',                           'test two chars' );
    ok( csv2pipe('a,b,abc,def,') eq 'a|b|abc|def|',         'test multiple strings' );
    ok( csv2pipe("abc,def,abc'xyz") eq "abc|def|abc'xyz",   'test single quote in string' );
    ok( csv2pipe('abc,def,abc"xyz') eq 'abc|def|abc"xyz',   'test double quote in string' );
    ok( csv2pipe('abc,def,"abc,xyz"') eq 'abc|def|abc,xyz', 'test double quoted comma does not get converted' );
    ok( csv2pipe("abc,def,'abc,xyz'") eq 'abc|def|abc,xyz', 'test single quoted comma does not get converted' );

    # this call does not work!!!
    # exit in csv2pipe.pl function main() will exit this testing script as well
    like(
        main(),        # first  param = argument to program
        qr/Usage:/,    # second param = expected result
        'test run program with no parameter'
    );                 # 3rd parameter = test description

    print "Tests Executed: ";
    done_testing();
    printf( "END---$0---%s---\n", scalar( localtime(time) ) );
    printf( "Program Run Time: %s second(s).\n", ( time - $^T ) );
}

      

Normal Test Output:

C:\workspace\csv2pipe>c:\perl\bin\perl csv2pipe_unit_testing.pl
START---csv2pipe_unit_testing.pl---Fri Sep 12 15:15:47 2014---
ok 1 - require 'csv2pipe.pl';
ok 2 - test empty string
ok 3 - test one char
ok 4 - test two chars
ok 5 - test multiple strings
ok 6 - test single quote in string
ok 7 - test double quote in string
ok 8 - test double quoted comma does not get converted
ok 9 - test single quoted comma does not get converted
Tests Executed: 1..9
END---csv2pipe_unit_testing.pl---Fri Sep 12 15:15:48 2014---
Program Run Time: 1 second(s).

      

Test exit on failure in sub main () exit:

C:\workspace\csv2pipe>c:\perl\bin\perl csv2pipe_unit_testing.pl
START---csv2pipe_unit_testing.pl---Fri Sep 12 15:20:49 2014---
ok 1 - require 'csv2pipe.pl';
ok 2 - test empty string
ok 3 - test one char
ok 4 - test two chars
ok 5 - test multiple strings
ok 6 - test single quote in string
ok 7 - test double quote in string
ok 8 - test double quoted comma does not get converted
ok 9 - test single quoted comma does not get converted
START---csv2pipe_unit_testing.pl---Fri Sep 12 15:20:49 2014---
Usage: csv2pipe_unit_testing.pl -i file.csv -o file.pipe
# Tests were run but no plan was declared and done_testing() was not seen.

      

+3


source to share


1 answer


If you can't turn exit

in die

, try it Test::Trap

. From a quick overview:



use Test::More;
use Test::Trap;

my @r = trap { some_code(@some_parameters) };
is ( $trap->exit, 1, 'Expecting &some_code to exit with 1' );
is ( $trap->stdout, '', 'Expecting no STDOUT' );
like ( $trap->stderr, qr/^Bad parameters; exiting\b/, 'Expecting warnings.' );

      

+2


source







All Articles