Test::More is_deeply 与字符串比较时不会漂亮打印 array/hashrefs

Test::More is_deeply does not pretty-print array/hashrefs when comparing against strings

当 Test::More 比较 arrayrefs 和 hashrefs 时,相应的诊断消息非常有用,并显示结构不同的第一个索引,无论嵌套深度如何。但是,当它将 arrayref 或 hashref 与简单标量进行比较时,它会在诊断消息中生成一个字符串化标量(具有内存地址和引用类型),这更难解释。

有没有办法配置 Test::More 以自定义方式(例如使用 Data::Dumper)漂亮打印数组或 hashrefs?

这是一个包含两个测试用例的示例。第一个让您深入了解程序中存在但未预料到的内容。第二个通知用户字符串和 arrayref 之间的类型不匹配,但不打印 arrayref 中的任何项目。

#!/usr/bin/env perl
use strict;
use warnings;
use Test::More tests => 2;

is_deeply(
    {
        a => [5],
    },
    {
        a => [5, 6, 8],
    },
    'compare two hashrefs structurally (very informative output)',
);

is_deeply(
    [5, 6, 8],
    "",
    'compare two "incompatible" values structurally (uninformative output)',
);

以及 TAP 输出:

1..2
not ok 1 - compare two hashrefs structurally (very informative output)
#   Failed test 'compare two hashrefs structurally (very informative output)'
#   at test-more-failure.pl line 6.
#     Structures begin differing at:
#          $got->{a}[1] = Does not exist
#     $expected->{a}[1] = '6'
not ok 2 - compare two "incompatible" values structurally (uninformative output)
#   Failed test 'compare two "incompatible" values structurally (uninformative output)'
#   at test-more-failure.pl line 16.
#     Structures begin differing at:
#          $got = ARRAY(0x7fe66b82cde8)
#     $expected = ''
# Looks like you failed 2 tests of 2.

查看 Test::More 中 is_deeply 的实现,似乎没有办法使用自定义漂亮打印机或配置模块的详细程度。至少 none 这对我来说是显而易见的。

这是我们比较引用和非引用时发生的情况:

https://metacpan.org/source/EXODIST/Test-Simple-1.302062/lib/Test/More.pm#L1121

好像是在调用_format_stack({vals => [...]})而不是_format_stack(...)

https://metacpan.org/source/EXODIST/Test-Simple-1.302062/lib/Test/More.pm#L1139

tl;dr 根据具体情况使用 is_deeply($this, $that) || diag explain $this

你好。 I'm the one to blame for is_deeply。它经过精心设计,不会在出现故障时吐出潜在的巨大数据结构。相反,它停在第一个差异处。出于这个原因,您可能不想全局 make is_deeply 转储其参数。如果类型错误,如果你期望苹果和斑马,那么知道有多少斑马和它们的生活故事没有多大意义。

没有支持的方法来更改其诊断,抱歉,而且不太可能有。 Test::More 正在被 Test2 取代。 Test::More 已在 Test2 之上实现,但出于向后兼容性原因未利用其功能。

您可以使用 Test2::Bundle::More for more direct access to Test2's features, but it is not 100% compatible, and it displays similar to how is_deeply does. However, it is much more flexible and you can probably figure out a way to alter its diagnostic behavior. Look into Test2::Compare.


回到您的问题...根据具体情况使用 explainexplain 使用 Data::Dumper,配置正确,转储数据结构。由于 Test::More 函数 return 无论它们通过还是失败,您都可以写成 is_deeply($this, $that) || diag explain $this。例如...

my $stuff = [5, 6, 8];
is_deeply $stuff, "" || diag explain $stuff;

not ok 2
#   Failed test at /Users/schwern/tmp/test.plx line 17.
#     Structures begin differing at:
#          $got = ARRAY(0x7f80b3803078)
#     $expected = ''
# [
#   5,
#   6,
#   8
# ]

diag 是打印故障诊断信息的方式(这是打印到 STDERR 的一种更礼貌的方式)。

Test::Differences 开始尝试 eq_or_diff( $got, $expected, $message ),它会打印出您的数据结构的漂亮表示,并清楚地突出显示确切的相同点和不同点。