使用Test::More在perl中进行单元和集成测试-如何捕获退出调用?
我有一个脚本,它将文件从csv分隔转换为管道分隔(csv2pipe.pl)使用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
然后将管道分隔的文件加载到数据库中。
我正在尝试为它运行单元测试(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.' );