7

有一个很棒的 Perl 模块 Test::More,每个人都使用它来进行单元测试。这是非常简单的脚本t/sample_1.t

use Test::More tests => 1;

fail('This test fails');

我想编写做同样事情的脚本,但没有 Test::More

我已经阅读了几个关于 TAP(测试任何协议)的文档,以了解如何编写脚本。我读了:

不幸的是,文档还不够。我不得不检查使用 Test::More 的脚本的输出,以发现我需要将诊断结果输出到 STDERR(文档中对此一无所知)。

因此,我编写了一个脚本,它与带有 Test::More 脚本的脚本完全一样。以下是清单t/sample_2.t

$| = 1;

print "1..1\n";
print "not ok 1 - This test fails\n";
print STDERR "#   Failed test 'This test fails'\n";
print STDERR "#   at t/sample_1.t line 3.\n";
print STDERR "# Looks like you failed 1 test of 1.\n";

exit 1;

但是当使用prove这两个脚本时输出不同的东西。对于不同的测试,“# Failed test 'This test failed'”prove行显示在不同的行上。这是屏幕截图:

Perl 证明 2 个样本单元测试的输出

我编写了一个测试脚本,它使用Capture::Tiny来检查两个脚本的 STDERR、STDOUT 和退出代码是否相同。该脚本显示两个脚本输出相同的内容。

我已将所有测试文件和测试脚本存储在GitHub repo中。

我的问题。我应该如何在没有 Test::More 的情况下编写 Perl 单元测试以获得与 Test::More 相同的输出。

PS如果你有兴趣我为什么需要这个。我需要这个来解决的 Perl 模块Test::Whitespaces的问题。

4

2 回答 2

2

虽然我完全不知道发生了什么,但我可以通过在任何其他输出到 STDERR 之前包含以下内容来使输出匹配(至少在视觉上):

print STDERR "\r";

这使得它们在穿过prove或普通旧时在视觉上匹配perl。然而,这不是Test::More 所做的。

您输出的 TAP 符合规范;如果prove想以与 TAP Test::More 输出不同的方式对待它,我认为这是prove. 就个人而言,当我编写测试模块时,我总是使用 Test::Builder 或包装的 Test::More 来输出 TAP。每一个都是一个核心模块。这似乎是大多数测试模块倾向于做的事情。

于 2013-06-30T08:29:03.260 回答
2

最后我发现了发生了什么。

霍布斯建议我使用 Test::Builder 我使用 Test::Builder创建了测试脚本,该脚本与使用 Test::More 的脚本一样工作(这里是)。

然后我开始检查Test::Builder的源代码,以找出这种行为的来源。这是 lib/TB2/Formatter/TAP/Base.pm 文件的一部分:

# Emit old style comment failure diagnostics
sub _comment_diagnostics {
    my($self, $result) = @_;

    ...

    # Start on a new line if we're being output by Test::Harness.
    # Makes it easier to read
    $self->$out_method("\n") if ($out_method eq 'err') and $ENV{HARNESS_ACTIVE};
    $self->$diag_method($msg);

    return;
}

所以,这就是答案。prove设置特殊的环境变量 HARNESS_ACTIVE和 Test::More 和朋友在打印到 STDERR 的任何诊断之前添加额外的换行符“\n”。

最后,我创建了输出与使用 Test::More 编写的脚本完全相同的测试脚本。脚本的源代码

我真的不喜欢这个解决方案。我和其他人花了很多时间才弄清楚发生了什么。我确信漂亮输出的任务应该在 TAP 解析器中解决,而不是在 TAP 生产者中解决。

=(

于 2013-07-01T04:44:50.547 回答