使用Test :: More和Test :: Deep打印失败的子测试

use*_*185 4 testing perl

我用Test::More和编写了一个大测试Test::Deep.该测试包含子测试.当我运行代码时,在最后一行我得到:

# Looks like you failed 3 tests of 25.
Run Code Online (Sandbox Code Playgroud)

如何打印指定失败的子测试的摘要?(每个子测试都有一个标题.)

Sch*_*ern 7

简短的回答:你做不到.

稍微长一点的答案:你必须修补Test :: BuilderTAP :: Harness.

Hacky回答:在subtest函数周围放置一个包装器,它捕获名称和结果(subtest(),就像所有测试函数一样,传递时返回true,失败时返回false)并在END块中输出额外的摘要信息.实施留给读者.

tl; dr信息......

Test :: Builder(以及整个Test生态系统)不报告摘要中的子测试.我不相信Test :: Builder的发布版本(0.9x)完全存储子测试的结果.子测试在Test :: Builder 0.9x中是一种可怕的黑客攻击.Test :: Builder 1.5更优雅地处理子测试,所以如果你想制作一个补丁,我会用1.5来做.

TAP :: Harness(并因此证明)不了解子测试,只要它关注它的垃圾被忽略.为了解决这个问题,每个子测试最后会产生一个额外的测试,这是Test :: Harness所理解的.

# TAP::Harness sees this line, the overall plan.
1..1
    # All this indented subtest info is ignored by TAP::Harness.
    ok 1
    ok 2
    not ok 3
    1..3
    # Looks like you failed 1 test of 3.
# TAP::Harness sees this line, and that all it knows about the subtest
# It doesn't even know its a subtest.
not ok 1 - foo
Run Code Online (Sandbox Code Playgroud)

TAP :: Harness需要修补以了解子测试,这是非常受欢迎的.

使用Test :: More自己的子测试函数作为指南的子测试包装器将如下所示:

use Test::Builder;

my @Failed_Subtests;
sub my_subtest {
    my $name = shift;

    # Call subtest
    my $tb = Test::Builder->new;
    my $subtest_ok = $tb->subtest($name, @_);

    # Record the name of any failing subtests
    push @Failed_Subtests, $name if !$subtest_ok;

    return $subtest_ok;
}

# When the test is over, show the failed subtests
END {
    if( @Failed_Subtests ) {
        diag sprintf "These subtests failed: %s", join(", ", @Failed_Subtests);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你使用my_subtest而不是subtest你会得到类似的东西:

# These subtests failed: bar, baz
# Looks like you failed 2 tests of 3.
Run Code Online (Sandbox Code Playgroud)

您可以替换Test :: More,而不是定义新的子测试函数.函数的主体看起来是一样的,但替换Perl函数的技术是另一个问题的主题.