gpt4 book ai didi

Perl 单元测试——子例程可测试吗?

转载 作者:行者123 更新时间:2023-12-03 00:57:39 25 4
gpt4 key购买 nike

我一直在阅读和探索 Perl 中的单元测试和测试驱动开发的概念。我正在研究如何将测试概念融入到我的开发中。假设我这里有一个 Perl 子例程:

sub perforce_filelist {

my ($date) = @_;

my $path = "//depot/project/design/...module.sv";
my $p4cmd = "p4 files -e $path\@$date,\@now";

my @filelist = `$p4cmd`;

if (@filelist) {
chomp @filelist;
return @filelist;
}
else {
print "No new files!"
exit 1;
}
}

子例程执行 Perforce 命令并将该命令的输出(文件列表)存储到 @filelist 数组中。这个子程序可以测试吗?测试返回的 @filelist 是否为空有用吗?我正在尝试自学如何像单元测试开发人员一样思考。

最佳答案

有几件事导致 perforce_filelist 子例程的测试比实际需要的更加困难:

  • p4 路径是硬编码的
  • p4 命令在子例程内部构造
  • p4 命令是固定的(因此,它始终是路径中的第一个 p4)
  • 直接从子例程输出
  • 您从子例程内部退出

但是,您的子例程的职责是获取文件列表并返回它。除此之外所做的任何事情都会让测试变得更加困难。如果您无法更改此设置,因为您无法控制它,那么您可以在将来编写如下内容:

#!perl -T

# Now perforce_filelist doesn't have responsibility for
# application logic unrelated to the file list
my @new_files = perforce_filelist( $path, $date );
unless( @new_files ) {
print "No new files!"; # but also maybe "Illegal command", etc
exit 1;
}

# Now it's much simpler to see if it's doing it's job, and
# people can make their own decisions about what to do with
# no new files.
sub perforce_filelist {
my ($path, $date) = @_;
my @filelist = get_p4_files( $path, $date );
}

# Inside testing, you can mock this part to simulate
# both returning a list and returning nothing. You
# get to do this without actually running perforce.
#
# You can also test this part separately from everything
# else (so, not printing or exiting)
sub get_p4_files {
my ($path, $date) = @_;
my $command = make_p4_files_command( $path, $date );
return unless defined $command; # perhaps with some logging
my @files = `$command`;
chomp @files;
return @files;
}

# This is where you can scrub input data to untaint values that might
# not be right. You don't want to pass just anything to the shell.
sub make_p4_files_command {
my ($path, $date) = @_;
return unless ...; # validate $path and $date, perhaps with logging
p4() . " files -e $path\@$date,\@now";
}

# Inside testing, you can set a different command to fake
# output. If you are confident the p4 is working correctly,
# you can assume it is and simulate output with your own
# command. That way you don't hit a production resource.
sub p4 { $ENV{"PERFORCE_COMMAND"} // "p4" }

但是,您还必须判断这种程度的分解对您来说是否值得。对于您不经常使用的个人工具来说,这可能工作量太大。对于你必须支持并且很多人使用的东西,这可能是值得的。在这种情况下,您可能需要 official P4Perl API 。这些值(value)判断取决于你。但是,分解问题后,进行更大的更改(例如使用 P4Perl)应该不会那么令人震惊。

<小时/>

作为旁注,而不是我建议解决此问题的方法,这是 & 且无参数列表的用例。在这个“加密上下文”中,子例程的参数列表是调用它的子例程的@_

这些调用不断地在链上传递相同的参数,这对于输入和维护来说很烦人:

    my @new_files = perforce_filelist( $path, $date );
my @filelist = get_p4_files( $path, $date );
my $command = make_p4_files_command( $path, $date );

使用 & 并且没有参数列表(甚至没有 ()),它会将 @_ 传递到下一个级别:

    my @new_files = perforce_filelist( $path, $date );

my @filelist = &get_p4_files;
my $command = &make_p4_files_command;

关于Perl 单元测试——子例程可测试吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44198069/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com