【问题标题】:Test::More doesn't know if test dies - so how do I test?Test::More 不知道测试是否会死 - 那么我该如何测试呢?
【发布时间】:2014-05-27 19:00:16
【问题描述】:

我正在将我的一堆脚本共有的一堆子例程收集到一个模块中。 (我应该早点这样做,但从继承的脚本开始。)我正在使用 Test::More 和 Module::Build 对 非常有用 示例 here 的工作进行建模

所有从文件读取或写入的子例程都包含一行open() or die "errmsg"。我正在为模块编写测试并遇到了这个问题。其中一个子例程检查路径是否指向某物,失败时死亡。在继承的脚本中,子例程如下所示:

sub checkExist {
  my ($type, $path) = @_;
  if ($type eq 'd') {
    if (! -d $path) {
      warn("dir not found: $path\n");
      die $pathNotFound;
    }
  }
  elsif ($type eq 'f') {
    if (! -f $path) {
      warn("file not found: $path\n");
      die $pathNotFound;
    }
    elsif (! -s $path) {
      warn("empty file: $path\n");
      die $emptyFile;
    }
  }
}

现在,我正在使用以下行进行测试:

is(HomeBrew::IO::checkExist('f', $0), '', "can checkExist find file $0 ?");

除非我选择一个不存在的路径,否则它工作正常,在这种情况下测试脚本会死掉,但测试成功,产生以下输出:

# Looks like your test exited with 2 just after 5.
Dubious, test returned 2 (wstat 512, 0x200)
All 5 subtests passed 

如果这是一个失败的测试(而不是一个可疑的通过),我更愿意,但由于这是遗留代码,我还希望这个子例程在失败时停止执行。该怎么办?对这么简单的函数编写测试是愚蠢的吗?

我已经编写了一个 checkExist2 函数,我将在未来使用它,如果成功则返回 undef,否则会返回一个非零错误(所以我可以在其他地方写 die if checkExist2())。欢迎其他不维护 checkExist 功能的建议。

【问题讨论】:

  • 可疑是失败,而不是成功。是什么让你说测试成功了?
  • @ysth - 我的假设是它会打印“ALL 测试通过”。当然,正确的解决方案是制定测试计划。
  • @DVK:是的,所有完成的测试都通过了。但是prove or Test::Harness::runtests() 会认为它是失败的。
  • @ysth:你说得对,可疑产生测试Result: FAIL,但所有子测试都通过了。

标签: perl testing module


【解决方案1】:

测试代码是否存在或因正确错误而死亡的正确方法是使用Test::Exception。您可以将此测试包装在其他测试用例中,因为它只需要一个 coderef:

use Test::More;
use Test::Exception;

lives_ok {
    is(HomeBrew::IO::checkExist('f', $0), '',
    "can checkExist find file $0 ?")
} '...and code does not die';

【讨论】:

  • @flies:我会把它们分开:my $exist; lives_ok { $exist = HomeBrew::IO::checkExist(...) } 'checkExist did not die'; is($exist, '', "can find file $0");。这样你总是可以运行两个测试。
【解决方案2】:

为什么不在您的测试模块中有一个辅助子例程,它将eval{} 包装在HomeBrew::IO::checkExist 调用周围并通过$@ 检查失败?

sub runcheckExist {
   my $res = eval { HomeBrew::IO::checkExist('f', $0) };
   # May want more logic here 
   # for checking $@ for specific error text pattern
   # or $res
   return $@ ? 1 : 0;
}
my $expect_to_die = 1;
is(runcheckExist(), $expect_to_die, "can checkExist find file $0 ?");

【讨论】:

  • 为什么不呢?因为 eval 是邪恶的,如果你发现自己需要它,很可能有一种更好的方法可以抽象出 eval 并处理所有边缘情况。
  • @Ether:说什么?是什么让你说 eval 是邪恶的? eval 是测试代码应该死的正确方法
  • @Ether: 所以 Test::Exception 是邪恶的,但它的调用者不是?我不买。尤其是 Try* 包装器; eval{} 和 $@ 检查是 perl 与其他语言 try/catch 的原生等价物(如果有一些 perlish 陷阱);强制使用语法糖级别是愚蠢的。
  • @DVK 这个回复教会了我一些关于 perl 的知识。
  • #define evil "隐约干扰以太的东西"
猜你喜欢
  • 1970-01-01
  • 2013-08-22
  • 1970-01-01
  • 2011-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-11
  • 2018-05-09
相关资源
最近更新 更多