如何在 Perl 测试套件中并行运行一些但不是所有测试?

Posted

技术标签:

【中文标题】如何在 Perl 测试套件中并行运行一些但不是所有测试?【英文标题】:How to run some but not all tests in a Perl test suite in parallel? 【发布时间】:2012-08-15 20:47:07 【问题描述】:

我有一个基于 Perl 的测试套件,其中包含 10,000 多个测试,我想让它们运行得更快。我已经使用-j 标志对prove 进行了测试,我发现我的大多数但不是所有测试都准备好并行运行。

虽然我可以努力使其余测试“并行友好”,但我希望总有一些测试不是。有什么好的方法来管理这个?我希望它能够轻松高效地运行整个测试集,并在需要时轻松将测试标记为“未准备好”。

以下是我看到的一些选项:

    prove could be patched to support some tests as not-parallel-ready Jenkins 被用于管理测试套件的运行。我可以将非并行测试拆分为他们自己的运行。换句话说,放弃并使用两次测试运行。 也许有一种方法可以将两个 TAP 结果流合并在一起,但我还没有恢复。

我不太关心如何管理例外列表。我可以在文件中保留一个列表作为测试工具基础设施的一部分,或者我可以在每个测试标头中放置一些东西来标记它,我们的测试工具可以动态确定异常列表。

(测试套件部分基于 Test::Class,我还将研究 Test::Class::Load 以加快它的速度。)

【问题讨论】:

【参考方案1】:

我找到了解决方案。它在aggregate_tests() for TAP::Harness 的文档中。它包含一个代码示例,说明我如何为此目的编写自己的工具:

...这很有用,例如,在某些测试应该 并行运行,但其他不适合并行执行。

my $formatter   = TAP::Formatter::Console->new;
my $ser_harness = TAP::Harness->new(  formatter => $formatter  );
my $par_harness = TAP::Harness->new(
       formatter => $formatter,
        jobs      => 9
    
);
my $aggregator = TAP::Parser::Aggregator->new;

$aggregator->start();
$ser_harness->aggregate_tests( $aggregator, @ser_tests );
$par_harness->aggregate_tests( $aggregator, @par_tests );
$aggregator->stop();
$formatter->summary($aggregator);

从那里看起来我可以:

子类 App::Prove 并覆盖 _runtests(),这是可以合并上述新功能的地方。 fork prove 以便它调用 My::App::Prove 而不是 App::Prove

现在我更好地理解了这些部分是如何组合在一起的,我可以看到如何为prove 创建一个补丁,它会添加一个像--exclude-from-parallel FILE 这样的选项,它允许你指定一个文件,其中包含一个列表要从并行测试中排除的测试文件。

2012-08-16 更新:我现在有一个针对 prove 的补丁,并已提交以供审核。你可以view and comment on the Pull Request。运行输出后不生成摘要。目前尚不清楚为什么。

【讨论】:

【参考方案2】:

到目前为止,我已经找到了解决此问题的最佳方法。事实证明,prove 自 2008 年以来一直支持将一些测试标记为按顺序运行而不是并行运行。它由 TAP::Parser::Scheduler 中一个相当花哨的“规则”系统支持,该系统允许复杂的规范并行和顺序测试运行的订购安排。

这是prove 的基本当前配方:

 # All tests are allowed to run in parallel, except those starting with "p"
 --rules='seq=t/p*.t' --rules='par=**'

我有一个新的pull request,它为这个特性添加了文档,并且已经开始讨论可能为基本异常提供更简单的语法。有关详细信息,请参阅拉取请求。

【讨论】:

【参考方案3】:

我找到了另一个宣传此功能的解决方案,但我只能让琐碎的案例发挥作用。使用Test::Steering。它允许我这样做:

include_tests(  jobs => 4 , @parallel_tests );
include_tests( @serial_tests  );

使用此解决方案,请注意:

在它真正起作用之前,我目前必须 patch the code to fix a basic bug 使用它多年来一直没有打补丁。 需要额外的代码来处理生成要运行的并行和串行测试列表。 我实际上并没有得到我真实世界测试的综合总结......两个部分都发出了自己的总结报告,所以它并没有真正起作用。也许我错过了什么,或者它坏了。

【讨论】:

【参考方案4】:

Test::Parallel 还提供了一种更简单的方法来并行运行一些测试 看看来自https://metacpan.org/pod/Test::Parallel的样本

【讨论】:

除了这不是在我的环境中构建的:(。它也非常复杂。我在大约一个小时内实现了一个更简单的解决方案,其中包含一些分叉和构建器->输出。如果我很乐意发布到 CPAN任何人都想要它。【参考方案5】:

另一种选择:为TAP::Harness 使用规则文件。

您可以在 YAML 文件(默认称为 testrules.yml)中构建自定义规则。我需要类似于你描述的东西,我可以用一个看起来像这样的 testrules.yml 文件来做到这一点:

--- 序列: # 未准备好并行的测试(将单独运行) - 序列: -t/test1.t - t/test2.t # 可以并行运行的测试 - 标准杆: # 其他所有内容的通配符 - **

在我的例子中,我将它与直接调用 App::Prove 的代码一起使用,而不是命令行 prove。但我认为它也适用于prove

【讨论】:

以上是关于如何在 Perl 测试套件中并行运行一些但不是所有测试?的主要内容,如果未能解决你的问题,请参考以下文章

如何并行运行机器人框架测试用例而不是并行测试套件?

Gradle 并行运行 TestNG 套件

如何在机器人框架中并行运行多个测试套件上的多个测试用例 | Python

Selenium GRID:并行运行多个 Robot Framework 测试套件

如何在单线程中运行 ScalaTest 套件?

在 Maven 构建中并行运行 junit 测试?