Re: [Perlunit-users] Comparing deeply nested data structures.
Status: Beta
                
                Brought to you by:
                
                    mca1001
                    
                
            | 
      
      
      From: Adrian H. <ad...@qu...> - 2007-05-16 23:26:53
      
     | 
| 
On 16 May 2007, at 18:17, Desilets, Alain wrote:
[snip]
> I want to easily compare the output of that method to expected  
> output, and if the two differ, get a good diagnostic message that  
> describes exactly how the two differ.
[snip]
> Is there something in Perl that would allow me to do this?
In Test::Unit there's assert_deep_equals() - for example:
     sub test_using_assert_deep_equals {
         my $self = shift;
         $self->assert_deep_equals(
             [ { hello =>1}, { world => 1 } ],
             [ { hello =>1}, { earth => 1 } ]
         );
     }
that gives you a diagnostic like
1) /Users/adrianh/Desktop/test.pl:53 - test_using_assert_deep_equals 
(Comparison::Test)
Structures begin differing at:
   $a->[1]{earth} = Does not exist
   $b->[1]{earth} = '1'
> I stumbled across cmp_deeply(), but I can't figure out how to use  
> it. It's part of a testing framework different from PerlUnit, and I  
> can't seem to be able to use it without running it inside that  
> other testing framework (which I don't have time to learn).
It's not that hard to shim the more popular Test::Builder based  
"assertion" modules into Test::Unit. The off-the-top-of-my-head  
greasy hack of:
{   package Test::Unit::MyTestCase;
     use base qw( Test::Unit::TestCase );
     use Test::Builder '0.7';
     use Carp qw( confess );
     sub assert_using {
         my ( $self, $test_coderef ) = @_;
         my $builder = Test::Builder->new;
         $builder->reset;
         $builder->plan( 'no_plan' );
         my $output = '';
         open my $output_fh, '>', \$output or die;
         $builder->output( $output_fh );
         $builder->failure_output( $output_fh );
         $builder->todo_output( $output_fh );
         $self->assert( $test_coderef->(), $output );
     }
}
would allow you to do things like:
{   package Comparison::Test;
     use base qw( Test::Unit::MyTestCase );
     use Test::More; # provides is_deeply
     sub test_using_is_deeply {
         my $self = shift;
         $self->assert_using( sub {
             is_deeply   [ { hello =>1}, { world => 1 } ],
                         [ { hello =>1}, { earth => 1 } ];
         } );
     }
     use Test::Deep; # provides cmp_deeply
     sub test_using_cmp_deeply {
         my $self = shift;
         $self->assert_using( sub {
             cmp_deeply(   [ { hello =>1}, { world => 1 } ],
                         [ { hello =>1}, { earth => 1 } ]
             );
         } );
     }
}
giving you diagnostics like
2) /private/var/tmp/folders.502/Cleanup At Startup/ 
test-201050484.793.pl:21 - test_using_cmp_deeply(Comparison::Test)
not ok 1
#   Failed test at /private/var/tmp/folders.502/Cleanup At Startup/ 
test-201050484.793.pl line 43.
# Comparing hash keys of $data->[1]
# Missing: 'earth'
# Extra: 'world'
3) /private/var/tmp/folders.502/Cleanup At Startup/ 
test-201050484.793.pl:21 - test_using_is_deeply(Comparison::Test)
not ok 1
#   Failed test at /private/var/tmp/folders.502/Cleanup At Startup/ 
test-201050484.793.pl line 33.
#     Structures begin differing at:
#          $got->[1]{earth} = Does not exist
#     $expected->[1]{earth} = '1'
However if you're going to be using a bunch of Test::Builder based  
assertions it might be easier to use Test::Group or <bias  
class="author"> Test::Class </bias> instead.
Cheers,
Adrian
 |