使用Test::More在perl中进行单元和集成测试-如何捕获退出调用?

使用Test::More在perl中进行单元和集成测试-如何捕获退出调用?,perl,unit-testing,csv,testing,Perl,Unit Testing,Csv,Testing,我有一个脚本,它将文件从csv分隔转换为管道分隔(csv2pipe.pl) 然后将管道分隔的文件加载到数据库中。 我正在尝试为它运行单元测试(csv2pipe\u unit\u test.pl,测试调用类似于(main()…)。 如果没有提供任何参数,csv2pipe.pl中的函数sub main()具有exit调用。 不幸的是,无法在测试调用中捕获退出调用,因此测试程序只能退出。 我无法执行eval{code}。它不捕获退出调用。它将捕获die和任何错误,但不捕获退出。 来自CPAN的pack

我有一个脚本,它将文件从csv分隔转换为管道分隔(csv2pipe.pl)
然后将管道分隔的文件加载到数据库中。
我正在尝试为它运行单元测试(csv2pipe\u unit\u test.pl,测试调用类似于(main()…)。
如果没有提供任何参数,csv2pipe.pl中的函数sub main()具有exit调用。
不幸的是,无法在测试调用中捕获退出调用,因此测试程序只能退出。
我无法执行eval{code}。它不捕获退出调用。它将捕获die和任何错误,但不捕获退出。
来自CPAN的package Capture::Tiny也一样。它不捕获退出调用。
您知道如何测试这个main()子函数并捕获退出调用吗?

文件: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;
}
测试的正常输出:

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).
sub main()退出失败时的测试输出:


如果您无法将
退出
转换为
死亡
,请尝试。从概要:

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.' );

您可以使用更方便的方法将CSV转换为管道分隔。您发明了轮子。我相信您知道,但是您是否考虑过使用
END
块来减少早期退出?还要注意,
如果有人可能想捕获发生的任何错误,请不要使用exit中止子例程。使用die Instead,如图所示,它可能被eval.
捕获。1.我不能使用Text::CSV,因为它未安装在工作中的目标Solaris系统上。我没有安装任何新软件包的权限。我可以将软件包下载并安装到我的主目录中,但不能安装到项目目录中(项目在不同的用户id下运行)因此,当我的程序投入生产时,它将不起作用,因为库不在那里。2.谢谢你的建议,我没有考虑结束{}block.3.是的,我可以将代码从exit更改为die。然后我可以使用eval进行捕获。但是,如果我正在测试一些很久以前编写的旧遗留脚本,该怎么办?我不想触碰旧代码,我只想为它编写一些单元测试。这听起来很有希望,我将尝试使用它并发回。谢谢。my@ret=trap{main();};比如($trap->stdout,qr/Usage:/,'testrunprogram with no parameter');太好了,很高兴它能为您工作!如果答案有效,请接受(单击勾号)。
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.
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.' );