Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Re^2: Diagnostic messages in Test::Deep

by KeighleHawk (Scribe)
on Jul 21, 2015 at 13:31 UTC ( [id://1135609]=note: print w/replies, xml ) Need Help??


in reply to Re: Diagnostic messages in Test::Deep
in thread Diagnostic messages in Test::Deep

yes, the array can be populated in random order :-).

The data set is slightly different than your example. The keys for each hash within the test run are the same. They differ between runs/tests.

Test 1 sample.

$got = [ { key_1 => "A", key_2 => "CC"} , { key_1 => "B", key_2 => "CC"} ] $expected = [ { key_1 => "B", key_2 => "CC"} , { key_1 => "A", key_2 => "CC"} ]

I want these to evaluate as equal, and they do with code like this (similar to yours):

return is deeply ( $got ? [ sort {$a->{key_1} cmp $b->{key_1}} $got ] : [] , $expected ? [ sort {$a->{key_1} cmp $b->{key_1}} $expected ] : [] , "Test array of hashes"

(the ternary operator is there because "no data returned" is also a valid/possible response).

The problem arises with Test 2 which has the following data:

$got = [ { key_3 => "A", key_2 => "CC"} , { key_3 => "B", key_2 => "CC"} ] $expected = [ { key_3 => "B", key_2 => "CC"} , { key_3 => "A", key_2 => "CC"} ]

The problem is the sorting key name has changed from 'key_1' to 'key_3' so my sort:

sort {$a->{key_1} cmp $b->{key_1}}

fails on the second data set. I could pass in the key names as variables, but was hoping to avoid that, especially since Test::Deep->bag() does exactly what I want.

The working Test::Deep code looks like this:

return = cmp_deeply ( $got ? [ $got ] : [] , bag ( $expected ? $expected : () ) );

(different brackets on bag due to return type, I need to double check that...)

So Test::Deep->bag() works for me because it does magic I don't have to when deciding how to sort the second array.

Robert Kuropkat

Replies are listed 'Best First'.
Re^3: Diagnostic messages in Test::Deep
by Athanasius (Archbishop) on Jul 22, 2015 at 04:43 UTC

    OK, I think I understand now; I hadn’t realised that separate hashes within the one array could legitimately contain the same keys with different values.

    I still think a generic procedure will work, it just needs a comprehensive sorting algorithm:

    #! perl use strict; use warnings; use Test::More tests => 2; use Test::Deep; my @x = ( { key_3 => 'A', key_2 => 'CC', key_4 => 'E', key_5 => 0 }, { key_3 => 'A', key_2 => 'DD', key_4 => 'F' }, ); my @y = ( { key_3 => 'A', key_2 => 'DD', key_4 => 'F' }, { key_5 => 0, key_3 => 'A', key_2 => 'CC', key_4 => 'E' }, ); cmp_deeply( \@x, bag(@y), 'Deep' ); print '-' x 20, "\n"; is_deeply( my_sort(@x), my_sort(@y), 'More' ); sub my_sort { my $f = sub { my @keys_a = sort keys %$a; my @keys_b = sort keys %$b; return -1 if @keys_a < @keys_b; return 1 if @keys_a > @keys_b; my $result = 0; $result ||= $keys_a[$_] cmp $keys_b[$_] || $a->{$keys_a[$_]} cmp $b->{$keys_b[$_]} for 0 .. $#k +eys_a; return $result; }; return [ sort $f @_ ]; }

    (For the basic idea, see How-do-I-sort-an-array-by-anything of perlfaq4.) Output:

    14:38 >perl 1314a_SoPW.pl 1..2 ok 1 - Deep -------------------- ok 2 - More 14:38 >

    Disclaimer: I’ve tested this only minimally; there may be corner cases I haven’t found. But I think this should allow you to return to using Test::More::is_deeply to get the benefit of its superior failure messages.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1135609]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (4)
As of 2024-04-19 03:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found