Simple Data Structure Equality

     

Test::More 's is( ) function checks scalar equality, but what about more complicated structures, such as lists of lists of lists? Good tests often need to peer into these data structures to test whether, deep down inside, they are truly equal. The first solution that may come to mind is a recursive function or a series of nested loops . Hold that thought, though ” Test::More and other test modules provide a better way with their comparison functions.

How do I do that?

Save this code as deeply.t :

 use Test::More tests => 1;     my $list1 =     [         [             [ 48, 12 ],             [ 32, 10 ],         ],         [             [ 03, 28 ],         ],     ];     my $list2 =     [         [             [ 48, 12 ],             [ 32, 11 ],         ],         [             [ 03, 28 ],         ],     ];     is_deeply( $list1, $list2, 'existential equivalence' ); 

Run it with prove -v to see the diagnostics:

 $  prove -v deeply.t  deeply....1..1     not ok 1 - existential equivalence     #     Failed test (deeply.t at line 23)     #     Structures begin differing at:     #          $got->[0][1][1] = '10'     #     $expected->[0][1][1] = '11'     # Looks like you failed 1 tests of 1.     dubious       Test returned status 1 (wstat 256, 0x100)     DIED. FAILED test 1       Failed 1/1 tests, 0.00% okay     Failed 1/1 test scripts, 0.00% okay. 1/1 subtests failed, 0.00% okay.     Failed Test Stat Wstat Total Fail  Failed  List of Failed     ---------------------------------------------------------------------------     deeply.t       1   256     1    1 100.00%  1 

What just happened ?

The example test compares two lists of lists with the is_deeply( ) function exported by Test::More . Note the difference between the two lists. Because the first array contains a 10 where the second contains an 11 , the test failed.

The output shows the difference between $list1 and $list2 . If there are multiple differences in the data structure, is_deeply( ) will display only the first. Additionally, if one of the data structures is missing an element, is_deeply( ) will show that as well.

What about...

Q:

How do I see the differences, but not the similarities, between data structures in my test output?

A:

Test::Differences exports a function, eq_or_diff( ) , that shows a Unix diff -like output for data structures. differences.t is a modified version of the previous test file that uses this function.

 use Test::More tests => 1;  use Test::Differences;  my $list1 = [       [           [ 48, 12 ],           [ 32, 10 ],       ],       [           [ 03, 28 ],       ],     ];     my $list2 = [       [           [ 48, 12 ],           [ 32, 11 ],       ],       [           [ 03, 28 ],       ],     ];  eq_or_diff( $list1, $list2, 'a tale of two references' );  

Running the file with prove produces the following output. Diagnostic lines beginning and ending with an asterisk ( * ) mark where the data structures differ .

 $  prove -v differences.t  differences....1..1     not ok 1 - a tale of two references     #     Failed test (differences.t at line 24)     # +----+-----------+-----------+     #  EltGot        Expected        # +----+-----------+-----------+     #    0[          [               #    1  [          [             #    2    [          [           #    3      48,        48,       #    4      12         12        #    5    ],         ],          #    6    [          [           #    7      32,        32,       # *   8      10         11   *     #    9    ]          ]           #   10  ],         ],            #   11  [          [             #   12    [          [           #   13      3,         3,        #   14      28         28        #   15    ]          ]           #   16  ]          ]             #   17]          ]               # +----+-----------+-----------+     # Looks like you failed 1 tests of 1.     dubious       Test returned status 1 (wstat 256, 0x100)     DIED. FAILED test 1       Failed 1/1 tests, 0.00% okay     Failed 1/1 test scripts, 0.00% okay. 1/1 subtests failed, 0.00% okay.     Failed Test   Stat Wstat Total Fail  Failed  List of Failed     --------------------------------------------------------------------     differences.t    1   256     1    1 100.00%  1 

Q:

How do I compare two strings, line-by-line ?

A:

Test::Differences shows the difference between multiline strings with its eq_or_diff( ) function. The following example tests the equality of two multiline strings using eq_or_diff( ) . Save it as strings.t :

 use Test::More tests => 1;     use Test::Differences;     my $string1 = <<"END1";     Lorem ipsum dolor sit     amet, consectetuer     adipiscing elit.     END1     my $string2 = <<"END2";     Lorem ipsum dolor sit     amet, facilisi     adipiscing elit.     END2     eq_or_diff( $string1, $string2, 'are they the same?' ); 

Running it with prove produces the following output:

 $  prove -v strings.t  strings....1..1     not ok 1 - are they the same?     #     Failed test (strings.t at line 16)     # +---+------------------------+------------------------+     #  LnGot                     Expected                     # +---+------------------------+------------------------+     #   1Lorem ipsum dolor sit   Lorem ipsum dolor sit        # *  2amet, consectetuer      amet, facilisi          *     #   3adipiscing elit.        adipiscing elit.             # +---+------------------------+------------------------+     # Looks like you failed 1 tests of 1.     dubious       Test returned status 1 (wstat 256, 0x100)     DIED. FAILED test 1       Failed 1/1 tests, 0.00% okay     Failed 1/1 test scripts, 0.00% okay. 1/1 subtests failed, 0.00% okay.     Failed Test Stat Wstat Total Fail  Failed  List of Failed     ---------------------------------------------------------------------     strings.t      1   256     1    1 100.00%  1 

The diagnostics resemble those from differences.t , with differing lines in the multiline string marked with asterisks .

Q:

How do I compare binary data?

A:

It's useful to see escape sequences of some sort in the differences, which is precisely what the Test::LongString module does. Test::LongString provides a handful of useful functions for comparing and testing strings that are not in plain text or are especially long.

Modify strings.t to use the is_string( ) function, and save it as longstring.t :

 use Test::More tests => 1;  use Test::LongString;  my $string1 = <<"END1";     Lorem ipsum dolor sit     amet, consectetuer     adipiscing elit.     END1     my $string2 = <<"END2";     Lorem ipsum dolor sit     amet, facilisi     adipiscing elit.     END2  is_string( $string1, $string2, 'are they the same?' );  

Run longstring.t using prove to see the following:


Note: Test::LongString also exports other handy stringtesting functions that produce similar diagnostic output. See the module's documentation for more information .
 $  prove -v longstring.t  longstring....1..1     not ok 1 - are they the same?     #     Failed test (longstring.t at line 16)     #          got: "Lorem ipsum dolor sit \x{0a}amet, consectetuer \x{0a}adipisc"...     #       length: 61     #     expected: "Lorem ipsum dolor sit \x{0a}amet, facilisi \x{0a}adipiscing "...     #       length: 57     #     strings begin to differ at char 23     # Looks like you failed 1 tests of 1.     dubious       Test returned status 1 (wstat 256, 0x100)     DIED. FAILED test 1       Failed 1/1 tests, 0.00% okay     Failed 1/1 test scripts, 0.00% okay. 1/1 subtests failed, 0.00% okay.     Failed Test  Stat Wstat Total Fail  Failed  List of Failed     ----------------------------------------------------------------------     longstring.t    1   256     1    1 100.00%  1 

The diagnostic output from Test::LongString 's is_string( ) escapes nonprinting characters ( \x{0a} ), shows the length of each string (61 and 57), and shows the position of the first different character.


Note: \x{0a} is one way to represent the newline character .


Perl Testing. A Developer's Notebook
Perl Testing: A Developers Notebook
ISBN: 0596100922
EAN: 2147483647
Year: 2003
Pages: 107

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net