如何优化 TAP 中 done_testing 的结束以及 perl 中测试结果的评估?

问题描述

我们有一个项目,我们在其中运行了一些测试,持续时间约为 3 小时。我观察到在生成结果的步骤中丢失了很多分钟。例如: 我有这个脚本 harness.pl

use strict;
use TAP::Harness;
use TAP::Formatter::HTML;
use TAP::Formatter::Console;

# Define Tests
my $tests = {
    "test_1" => {
        test    => 'script.t',args    => ['--server',"server_1"]
    },# "test_2" => {
        # test  => 'script.t',# args  => ['--server',"server_2"]
    # },};

# Get arguments
my $test_args = {};
$test_args->{$_} = $tests->{$_}->{args} foreach (sort keys %$tests);

# Define formatter
# my $fmt = TAP::Formatter::HTML->new();
# $fmt->output_file( "report.html" );
my $fmt = TAP::Formatter::Console->new({verbosity=>1});


# Start testing
my $harness = TAP::Harness->new( {
        test_args => $test_args,formatter => $fmt,merge => 1,jobs => 1,} );

my $result = $harness->runtests(get_tests($tests));

print( "$0 Run Time: " . ( time - $^T ) . " second(s).\n");
print "Passed: ". scalar $result->passed . "\n";
print "Failed: ". scalar $result->failed . "\n";
print "Errors: ". scalar $result->has_errors . "\n";


sub get_tests{
    
    my ($tests) = @_;
    
    my @tests_to_run;
    TEST: foreach my $test (sort keys %$tests){
        # some filtering...
        push @tests_to_run,[$tests->{$test}->{test},$test] 
    }
    # some prints...
    return @tests_to_run;
}

还有一些测试,让我们以以下 script. 为例:

use strict;
use warnings;

use Test::More;
use Getopt::Long qw(GetOptions);


my ($server);
GetOptions(
    'server|s=s'            => \$server,) or die "[ERROR] Invalid options passed to $0\n";


my $number_of_tests = 100000;
plan tests => 2 + $number_of_tests;


ok (1,"start");
foreach my $test_nr (0..$number_of_tests-1){
    ok(1,"Test numbber: $test_nr in $server");
}
ok ($server eq 'server_1',"Finished");
done_testing;
print( "$0 Run Time: " . ( time - $^T ) . " second(s).\n");

现在我使用 HTML 报告运行测试:

# Define formatter
my $fmt = TAP::Formatter::HTML->new();
$fmt->output_file( "report.html" );

我得到以下结果:

好的 100002 - 完成
script.t 运行时间:34 秒。 线束.pl 运行时间:42 秒。
通过:100002
失败:0
错误:0
所以在完成脚本后 8 秒。

之后我尝试使用默认的控制台格式化程序:

# Define formatter
my $fmt = TAP::Formatter::Console->new({verbosity=>1});

结果:

好的 100002 - 完成
script.t 运行时间:34 秒。
好的
所有测试均成功。
文件=1,测试=100002,34 秒(16.20 usr + 3.61 sys = 19.81 CPU)
结果:通过
线束.pl 运行时间:34 秒。
通过:100002
失败:0
错误:0

所以这看起来很不错,这让我认为问题来自创建一个非常大的 HTML 报告,在本例中将生成一个 13,854 KB HTML 文件。

所以我从这个简单的例子中跳到了我的项目中。并运行一个简化版本的我的测试,它会生成如下所示的报告:

enter image description here

正如您所看到的,这并不是大量的测试,只有大约 35 个,文件为 35 KB 我认为不会有很多计算问题。

然后我查看具有相同结构的日志,在其中打印脚本的最后一行,我得到了这种时间差:

t/long-test.t 运行时间:117 秒。
# 看起来你没有通过 34 的 2 次测试。
通过:32
失败:2
错误:2
Harness.pl 运行时间:212 秒。

我又想,这个 HTML 库肯定有问题。所以我全力以赴并删除 HTML 报告并仅使用控制台格式化程序:

# 在 t/mylongtest.t 第 237 行。
t/mylongtest.t 运行时间:128 秒。
# 看起来你没有通过 34 的 2 次测试。
可疑,测试返回 2 (wstat 512,0x200)
2/34 次测试失败

测试总结报告
-------------------
mylongtest (Wstat: 512 测试: 34 失败: 2)
失败的测试:33-34
非零退出状态:2
文件=1,测试=34,215 秒(0.22 usr + 0.12 sys = 0.34 CPU)
结果:失败
通过:32
失败:2
错误:2
Harness.pl 运行时间:216 秒。

然后我再次得到了从测试结束的 128 秒到安全带结束的 216 秒的这种克雷差异。

我试图完全删除线束脚本并仅使用证明,我得到了相同的

所以我的问题是。 done_testing/测试结束与测试工具结果报告之间发生了什么,我可以做些什么来改进?

更新:我终于能够在一个最小的例子中重现这个问题,似乎问题不是 TAP,而是在脚本末尾用垃圾收集器或类似的东西发生了什么.我创建了两个脚本,第一个 delete_me.pl:

use strict;
use JSON;

my $huge_json_string = '{';

foreach my $i (0..20000000){
    $huge_json_string .= '"key_'.$i.'": "some_value'.$i.'",';
}
$huge_json_string =~ s/,$/}/;#
print "String generated\n";
my $all_to_ram = decode_json($huge_json_string);
print "Hash generated\n";

print( "$0 Run Time: " . ( time - $^T ) . " second(s).\n");

现在我从其他脚本调用它delete_me_caller.pl

use strict;

system("perl delete_me.pl");
print( "$0 Run Time: " . ( time - $^T ) . " second(s).\n");

还有惊喜:

生成的字符串
哈希生成
delete_me.pl 运行时间:20 秒。
delete_me_caller.pl 运行时间:42 秒。

因此,与生成数据并将其加载到内存相比,结束脚本需要更多时间。 注意:对于此脚本,我使用的是带有 32GB 内存和 i7 8650 U 的个人计算机,因此在内存或电源较少的情况下,这可能需要更长的时间。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)