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

nck*_*nck 2 testing perl tap

我想利用这个库来漂亮地打印我的测试的差异,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 '$0'", {context=>$context}); # <- I don't want to count this
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我希望在脚本结束时执行测试,这两个测试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");
...
Run Code Online (Sandbox Code Playgroud)

lib.pm

...
sub some_function_in_other_file_or_library{
...
   eq_or_diff(...)
   return $bool;
}
...
Run Code Online (Sandbox Code Playgroud)

我提到这一点是因为我尝试过substest,但我也无法使其正常工作,而且我现在主要不必知道 lib 中发生的事情,否则我认为我可以使用done_testing($planned_tests+1):

lib.pm

use Test::More tests => 2;
...
ok(some_function_in_other_file_or_library(), "name_of_the_test");
...
Run Code Online (Sandbox Code Playgroud)

摘要:我如何制作类似于:

...
sub some_function_in_other_file_or_library{
...
   eq_or_diff(...)
   return $bool;
}
...
Run Code Online (Sandbox Code Playgroud)

bri*_*foy 5

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

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

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

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);
    }
Run Code Online (Sandbox Code Playgroud)

第二部分对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;
    }
Run Code Online (Sandbox Code Playgroud)

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

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 ) );
}
Run Code Online (Sandbox Code Playgroud)