如何使用 Test::more 忽略 perl 中的 TAP 结果?

How can I ignore a TAP result in perl with Test::more?

我想利用这个库来漂亮地打印我的测试的差异 Test::Differences; 但我不想在我的计划中计算它,因为它只是用于我的用例中的调试。

所以我创建了一个这个问题的最小示例来重现这个问题,我知道这样做是不“正确”的,但这是对问题的一个很好的说明。

use strict;
use warnings;
use utf8::all;
use open ':std', ':encoding(UTF-8)';

use Test::Differences;
use Test::Deep::NoTest qw(cmp_details deep_diag);
use Test::More tests => 2;
use JSON;

my $context = 1;
my $extracted_ref = {
    a => '1',
    b => '2',
    c => '3',
    d => '4',
};
my $reference_ref = {
    a => '1',
    b => '3',
    c => '3',
    d => '4',
};

my ($is_compare_ok, $stack) = cmp_details($extracted_ref,$reference_ref);
my $json_reference = JSON->new->canonical->encode($reference_ref);
my $json_extracted = JSON->new->canonical->encode($extracted_ref);

ok(1);
if ($is_compare_ok){
    ok(1);
    return 1;                               
}else{                                  
    ok(0);
    eq_or_diff($reference_ref, $extracted_ref, "Error in '[=11=]'", {context=>$context}); # <- I don't want to count this
    return 0;
}

我希望在脚本末尾执行测试,其中两个 ok 是在该过程中完成的。但是函数 eq_or_diff 向 TAP 会话添加了一个新测试,因此脚本以执行 3 个测试结束,因此 done_testing() 期望 2 但得到 3.

这是一个最小的例子,但通常我有一个主脚本:

main.t

use Test::More tests => 2;
...
ok(some_function_in_other_file_or_library(), "name_of_the_test");
...

lib.pm

...
sub some_function_in_other_file_or_library{
...
   eq_or_diff(...)
   return $bool;
}
...

我提到这个是因为我尝试使用 substest 但我无法使它工作,而且我主要不必知道库中发生了什么,否则我想我可以使用 done_testing($planned_tests+1):

lib.pm

use Test::More tests qw/subtest/;
subtest 'An example subtest' => sub {
    plan tests => 1;
 
    eq_or_diff(...)
};

总结:我怎样才能做出类似的东西:

do_not_add_to_tap(eq_or_diff(...))
# or 
increased during runtime the planned tests
plan() = plan()+1...

Test::Differences 和朋友们真的在为你做两件事,然后通过将它与测试框架紧密耦合来使它复杂化。这没什么大不了的,因为它实际上只是包装了您可以直接使用的其他模块的东西。

首先,它使用Data::Dumper通过设置各种参数来输出可预测的序列化,例如SortKeys。其次,它使用 Text::Diff 来比较那些转储的行。

所以,你自己做吧。这是第一部分,只是 returns 表示转储的单个字符串,适用于字符串比较以查看它们是否相等:

sub dump_it {
    my( $arg ) = @_;
    local $Data::Dumper::Deparse   = 1;
    local $Data::Dumper::Indent    = 1;
    local $Data::Dumper::Purity    = 0;
    local $Data::Dumper::Terse     = 1;
    local $Data::Dumper::Deepcopy  = 1;
    local $Data::Dumper::Quotekeys = 0;
    local $Data::Dumper::Useperl   = 1;
    local $Data::Dumper::Sortkeys  = 1;
    Data::Dumper::Dumper($arg);
    }

第二部分与Text::Diff做类似的事情。它设置了各种参数,您可以根据口味调味。我做这个是为了传递两个字符串,我把它们变成数组引用中的行(因为这都在内存中):

sub my_diff {
    state $rc = require Text::Diff;
    my( $got, $expected, $context ) = @_;

    $context //= 3;  # lines around the diff to show

    my $diff = Text::Diff::diff
        [ split /^/m, dump_it( $got ) ],
        [ split /^/m, dump_it( $expected ) ],
      { CONTEXT     => $context,
        STYLE       => 'Table',
        FILENAME_A  => 'got',
        FILENAME_B  => 'expected',
        OFFSET_A    => 1,
        OFFSET_B    => 1,
        INDEX_LABEL => "Ln",
      };
    chomp $diff;
    $diff .= "\n";

    $diff;
    }

所以现在你的程序的内容是这样的:

my $is_same = dump_it( $reference_ref ) eq dump_it( $extracted_ref );

pass();
if ($is_same){
    pass();
}else{
    fail();
    note( my_diff( $reference_ref, $extracted_ref, 1 ) );
}