问题描述
我想利用这个库来漂亮地打印我的测试 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',};
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;
}
我希望在脚本结束时执行测试,在此过程中完成的两个 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
并且我也无法使它工作,而且我现在主要不必知道 lib 中发生的事情,否则我认为我可以只使用 {{1 }}:
done_testing($planned_tests+1)
lib.pm
总结:我如何制作类似于:
use Test::More tests qw/subtest/;
subtest 'An example subtest' => sub {
plan tests => 1;
eq_or_diff(...)
};
解决方法
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);
}
第二部分对 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 ) );
}