【问题标题】:Prove returns inconsistent test results with Test::More and .tap extensionProve 使用 Test::More 和 .tap 扩展名返回不一致的测试结果
【发布时间】:2025-11-25 06:35:01
【问题描述】:

尝试使用Test::More 对名为test.tap 的文件进行基本测试:

use Test::More tests => 2;

is( 1, 1 );
is( 2, 2 );

针对此测试运行 prove 会导致失败:

$ prove test.tap
test.tap .. No subtests run

Test Summary Report
-------------------
test.tap (Wstat: 0 Tests: 0 Failed: 0)
  Parse errors: No plan found in TAP output
Files=1, Tests=0,  0 wallclock secs ( 0.02 usr +  0.00 sys =  0.02 CPU)

但是 Perl 给出了一个看似有效的 TAP 输出:

$ perl test.tap
1..2
ok 1
ok 2

prove 版本是:

$ prove --version
TAP::Harness v3.35 and Perl v5.22.1

另外,我发现在测试文件上添加shebang#!会导致测试结果间歇性通过

#!/usr/bin/perl

use Test::More tests => 2;

is( 1, 1 );
is( 2, 2 );

成功时(4 次通过 ~1 次):

t/test.tap .. ok
All tests successful.
Files=1, Tests=2,  0 wallclock secs ( 0.03 usr  0.00 sys +  0.01 cusr  0.00 csys =  0.04 CPU)
Result: PASS

我还发现将文件重命名为test.t 会导致每次测试都通过。

在尝试在旧版本中查找错误时,我已在运行 Ubuntu 16.04.2 的全新 DigitalOcean Droplet 和具有 TAP::Harness v3.36_01 和 Perl v5.24.1 的 Debian 8 主机上复制了此问题。

我希望避免“将所有文件重命名为 .t 扩展名”作为答案。我不确定TAP::Harness 认为这两个扩展之间的区别是什么,并且找不到任何文档或源代码中的区别所在。

非常感谢您对正在发生的事情进行任何澄清。

【问题讨论】:

  • 你需要告诉它如何运行测试:prove --exec /bin/perl test_more.tap
  • 我已经用 shebang 线确认了间歇性传递,并且很想知道它是如何传递的......当我使用 file-option extensions 参数来证明时,我也会遇到同样的情况:它通过了大约 1/4 的时间。

标签: perl tap


【解决方案1】:

.tap 扩展名告诉证明test.tap 是一个包含 TAP 的文本文件。它不会将其作为 Perl 程序执行,它只是读取文件并尝试将其解析为 TAP。您可以通过prove -v 看到这一点。

$ prove -v test.tap
test.tap .. 
use Test::More tests => 2;
is(1,1);
is(2,2);

No subtests run 

Test Summary Report
-------------------
test.tap (Wstat: 0 Tests: 0 Failed: 0)
  Parse errors: No plan found in TAP output
Files=1, Tests=0,  0 wallclock secs ( 0.02 usr +  0.00 sys =  0.02 CPU)
Result: FAIL

相反,执行测试程序的约定是test.t

$ mv test.tap test.t
$ prove -v test.t
test.t .. 
1..2
ok 1
ok 2
ok
All tests successful.
Files=1, Tests=2,  0 wallclock secs ( 0.03 usr  0.00 sys +  0.04 cusr  0.00 csys =  0.07 CPU)
Result: PASS

请参阅TAP::Parser::SourceHandler::File 了解更多信息。


另外,我发现在测试文件中添加shebang会导致测试结果间歇性通过:

正在发生的事情是各种 TAP::Parser::SourceHandler 插件都在投票决定它是什么,这是一个平局。 TAP::Parser::SourceHandler::Perl 看到 "a shebang ala "#!...perl" 并投票 0.9。TAP::Parser::SourceHandler::File 看到 .tap 扩展名并投票 0.9。您可以通过设置 TAP_HARNESS_SOURCE_FACTORY_VOTES 环境来查看变量。

$ TAP_HARNESS_SOURCE_FACTORY_VOTES=1  prove test.tap
votes: TAP::Parser::SourceHandler::File: 0.9, TAP::Parser::SourceHandler::Perl: 0.9
test.tap .. ok   
All tests successful.
Files=1, Tests=2,  0 wallclock secs ( 0.03 usr  0.00 sys +  0.05 cusr  0.00 csys =  0.08 CPU)
Result: PASS

$ TAP_HARNESS_SOURCE_FACTORY_VOTES=1  prove test.tap
votes: TAP::Parser::SourceHandler::Perl: 0.9, TAP::Parser::SourceHandler::File: 0.9
test.tap .. No subtests run 

Test Summary Report
-------------------
test.tap (Wstat: 0 Tests: 0 Failed: 0)
  Parse errors: No plan found in TAP output
Files=1, Tests=0,  0 wallclock secs ( 0.02 usr +  0.01 sys =  0.03 CPU)
Result: FAIL

然后处理程序按投票排序。由于 Perl 的排序不稳定,也就是说,如果两个条目相等,它不会保留它们的顺序,因此任何一个处理程序都可以排在首位。即使使用稳定排序,它也是从keys %handlers 排序的,每个进程都会以不同的顺序出现。 Here's the code for that.

对于一个测试工具来说,它的决定不是确定性的,这是不好的。它可能应该抛出一个错误。我还注意到它使用了字符串比较,这可能是错误的。

I've submitted a patch to make ties an error.

【讨论】:

  • 优秀的答案。 “测试工具在其决策中不具有确定性是不好的” 我同意,尽管如果Test::Harness 确定性的,则不会出现此问题。您会将此作为 Perl 错误提出吗?
  • @Borodin Already submitted a PR。 :)
  • 我真的不喜欢以与叙事英语相同的风格呈现的代码和数据。例如,“TAP::Parser::SourceHandler::Perl 看到”a shebang ala “#!...perl”不是我知道的语言。 Markdown 有反引号来标记预格式化的文本,我想知道你为什么不使用它?
最近更新 更多