我正在撰寫一個單元測驗,我必須檢查兩個散列變數(散列的散列)的關鍵結構是否相同。鍵值可以不同。散列的深度是任意的。
這Test::Deep似乎是理想的,但我無法弄清楚如何cmp_deeply忽略這些值。
use Test::Deep;
my %hash1 = ( key1 => "foo", key2 => {key21 => "bar", key22 => "yeah"});
my %hash2 = ( key1 => "foo", key2 => {key21 => "bar", key22 => "wow"});
cmp_deeply(\%hash1, \%hash2, "This test should not fail");
輸出:
not ok 1 - This test should not fail
# Failed test 'This test should not fail'
# at demo.pl line 13.
# Compared $data->{"key2"}{"key22"}
# got : 'yeah'
# expect : 'wow'
如果散列具有已知結構,我可以使用帶有 values 的測驗變數ignore()。但是,就我而言,最好的解決方案是我不必更新測驗代碼中的結構。
我嘗試遍歷%hash1usingData::Walk并檢查每個鍵是否存在,%hash2但發現很難從$Data::Walk::container值中獲取當前鍵。
關于合適的比較工具的任何想法?
uj5u.com熱心網友回復:
看來你需要忽略這些結構中的葉子,否則會比較。
然后可以比較兩個結構之間的所有路徑到葉子,而忽略葉子。
模塊Data::Leaf::Walker可以幫助解決這個問題,生成所有葉子的路徑陣列。然后這些需要進行比較,Test::Deep與它的包比較只是工具。
use warnings;
use strict;
use feature 'say';
use Data::Leaf::Walker;
use Test::More qw(no_plan);
use Test::Deep;
my %h1 = (key1 => "foo", key2 => {key21 => "bar", key22 => "yeah"});
my %h2 = (key1 => "foo", key2 => {key21 => "bar", key22 => "wow"});
my @key_paths_h1 = Data::Leaf::Walker->new(\%h1)->keys;
my @key_paths_h2 = Data::Leaf::Walker->new(\%h2)->keys;
# Now compare @key_paths_h1 and @key_paths_h2
# Order of arrayrefs in the top-level arrays doesn't matter
# but order of elements in each arrayref does
cmp_bag(\@key_paths_h1, \@key_paths_h2, 'key-paths');
這按預期列印,ok 1 - key-paths。更改任何鍵最終在not ok 1 ...
一旦我們開始,我想提一下該模塊提供了一個迭代器
my $walker = Data::Leaf::Walker->new($data_structure_ref);
while ( my ($keys_path, $value) = $walker->each ) {
say "[ @$keys_path ] => $value"
}
這樣我們就可以得到路徑和它們的值,一次一個。只有幾個,但精心挑選的方法。請參閱檔案。
uj5u.com熱心網友回復:
以下是如何手動執行此操作的示例:
use strict;
use warnings;
use experimental qw(signatures);
use Test::More;
{
my %hash1 = ( key1 => "foo", key2 => {key21 => "bar", key22 => "yeah"});
my %hash2 = ( key1 => "foo", key2 => {key21 => "bar", key22 => "wow"});
ok(cmp_keys(\%hash1, \%hash2), "Hash keys identical");
}
done_testing();
sub cmp_keys( $hash1, $hash2 ) {
my @keys1 = flatten_keys( $hash1 );
my @keys2 = flatten_keys( $hash2 );
return 0 if @keys1 != @keys2;
for my $i (0..$#keys1) {
return 0 if $keys1[$i] ne $keys2[$i];
}
return 1;
}
sub flatten_keys( $hash ) {
my @keys;
my $prefix = '';
_flatten_keys( $hash, $prefix, \@keys);
return sort @keys;
}
sub _flatten_keys ( $hash, $prefix, $keys) {
# $; The subscript separator for multidimensional array emulation,
# default value is "\034" = 0x1C
my $sep = $;;
for my $key (keys %$hash) {
if (ref $hash->{$key} eq "HASH") {
_flatten_keys( $hash->{$key}, $prefix . $key . $sep, $keys );
}
push @$keys, $prefix . $key;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/316270.html
