I needed to be able to check that two hashes have the same contents as part of a test suite. A Super Search turned up How to test equality of hashes? which has answers for the equality bit, but doesn't address the reporting bit.

The following code uses List::Compare::Functional to assist in comparing two hashes and reporting differences between them. Note that the application specific warning strings may need to be adjusted for your context. :-)

use List::Compare::Functional qw(get_unique get_complement); sub hashesEqual { my ($have, $want) = @_; my @keysHave = sort keys %$have; my @keysWant = sort keys %$want; my @haveOnly = get_unique ([\@keysHave, \@keysWant]); my @wantOnly = get_complement ([\@keysHave, \@keysWant]); if (@haveOnly) { warn 'Unexpected parameters ' . (join ',', @haveOnly) . " for +email send\n"; return; } if (@wantOnly) { warn 'Expected parameters ' . (join ',', @haveOnly) . " missin +g for email send\n"; return; } my $ok = 1; for (@keysHave) { next if $have->{$_} eq $want->{$_}; $ok = undef; warn "Email send parameter $_ expected '$want->{$_}', got '$ha +ve->{$_}'\n"; } return $ok; }

Replies are listed 'Best First'.
Re: Testing hash equality and reporting differences
by davidrw (Prior) on Oct 18, 2006 at 23:30 UTC
    alternatively (esp since you mention it's for a test suite), the docs for Test::More's is_deeply() method mention Test::Differences and Test::Deep:

    Header:
    #!/usr/bin/perl use strict; use warnings; my %h1 = ( a=>1, b=>2, c=>3 ); my %h2 = ( a=>3, b=>2, d=>4, e=>5 );
    Using Test::More
    use Test::More qw/no_plan/; is_deeply( \%h1, \%h2, "h1 vs h2" ); __END__ not ok 1 - h1 vs h2 # Failed test 'h1 vs h2' # in /tmp/h at line 10. # Structures begin differing at: # $got->{e} = Does not exist # $expected->{e} = '5' 1..1 # Looks like you failed 1 test of 1.
    Using Test::Differences
    use Test::More qw/no_plan/; use Test::Differences; eq_or_diff \%h1, \%h2, "testing hashes"; __END__ not ok 1 - testing hashes # Failed test 'testing hashes' # in /tmp/h at line 11. # +----+-----------+----+-----------+ # | Elt|Got | Elt|Expected | # +----+-----------+----+-----------+ # | 0|{ | 0|{ | # * 1| a => 1, * 1| e => 5, * # | | * 2| a => 3, * # | 2| b => 2, | 3| b => 2, | # * 3| c => 3 * 4| d => 4 * # | 4|} | 5|} | # +----+-----------+----+-----------+ 1..1 # Looks like you failed 1 test of 1.
    Using Test::Deep
    use Test::More qw/no_plan/; use Test::Deep; cmp_deeply \%h1, \%h2, "testing hashes"; __END__ not ok 1 - testing hashes # Failed test 'testing hashes' # in /tmp/h at line 11. # Comparing hash keys of $data # Missing: 'd', 'e' # Extra: 'c' 1..1 # Looks like you failed 1 test of 1.

      Thanks for that - even better!


      DWIM is Perl's answer to Gödel