Moose Growing Pains

Its test round up day here in the Moose-Pen

Now that my baby Moose is almost all grown up it is time to go back and look at some of the missing bits in my test suits. In my last post I fixed up the default 'view' for all the 'element' attributes that my be present on a Database::Accessor.

I have checked my test suite and I at least test the elements attribute to a few levels of recursion in '31_elements.t'. Looking at that test suit I think I will pull the eight 'view' tests out of there and and create a new test case '57_dad_elements.t' that will cover those eight and all the other 'view' tests for the DAD.

Like 98.956% of my other tests I start with a hash-ref to set the Database::Accessor, and I will just create one great big one to cover all test conditions for the static attributes and then before I test I will add in at least one each of the dynamic attributes and then do my tests.

Now not to bore you with many many lines of hash entries and simple tests here is just one example where I have this 'element' attribute;


...
},
{
function => 'left',
left => { name => 'salary' },
right => {
expression => '*',
left => { name => 'bonus' },
right => { param => .05 }
}
},


which happens to be the third items on the array, (index 2) and these tests associated with it;

ok(
$dad->elements->[2]->left->view eq 'People',
'Third element left inherits view'
);
ok( $dad->elements->[2]->right->left->view eq 'People',
'Third element right inherits view' );

simple enough. I was thinking of doing some sort of re-factoring as that pattern is repeated many times over but I decided against as this test is very easy to read and understand in case some-one wants to learn in the same way I do by poking about in test suites.

Now comes the intereing part of today's post.

As I was plugging away with the above I notice that on my 'conditions' attribute no matter how I tried to configure my input hash they always came out the same, an array-ref of 'Condition' classes each having an 'predicates' attribute of a single elements array-ref so from this


bless( {
'predicates' => [
bless( {
'operator' => '=',
'left' => bless( {
'view' => 'People',
'name' => 'First_2'
}, 'Database::Accessor::Element' ),
'right' => bless( {
'view' => 'other',
'name' => 'First_2'
}, 'Database::Accessor::Element' ),
'close_parentheses' => 0,
'condition' => 'AND',
'open_parentheses' => 0
}, 'Database::Accessor::Predicate' )
]
}, 'Database::Accessor::Condition' ),

to this;

bless( {
'predicates' =>
bless( {
'operator' => '=',
'left' => bless( {
'view' => 'People',
'name' => 'First_2'
}, 'Database::Accessor::Element' ),
'right' => bless( {
'view' => 'other',
'name' => 'First_2'
}, 'Database::Accessor::Element' ),
'close_parentheses' => 0,
'condition' => 'AND',
'open_parentheses' => 0
}, 'Database::Accessor::Predicate' )
}, 'Database::Accessor::Condition' ),

Funny how you find these things out so late in the game.


Taking a look at Accessor.pm the above 'predicates' attribute is expressed in the 'Database::Accessor::Roles::PredicateArray' role;


package
Database::Accessor::Roles::PredicateArray;
use Moose::Role;
use MooseX::Aliases;
use namespace::autoclean;

has predicates => (
traits => ['Array'],
is => 'rw',
isa => 'ArrayRefofPredicates',
coerce => 1,
alias => 'conditions',
handles => { predicates_count => 'count', },
);


and is only used in two classes 'Database::Accessor::Condition' and 'Database::Accessor::Link'. Having a little time today and feeling somewhat adventurous, I first checked in all my code, so I can go back if I mess things up, and I made the following change;

        Database::Accessor::Condition;
        use Moose;
        extends 'Database::Accessor::Base';
--        with qw(Database::Accessor::Roles::PredicateArray);
++        has predicates => (
++            is      => 'rw',
++            isa     => 'Predicate',
++            coerce  => 1,
++            alias   => 'conditions',
++        );

        1;
    }


and I gave 33_conditions.t a run and got;


You cannot coerce an attribute (predicates) unless its type (Predicate) has a coercion at;

Easy enough to fix with this;

...
coerce 'Gather', from 'HashRef', via { Database::Accessor::Gather->new( %{$_} ) };
++coerce 'Predicate', from 'HashRef', via { Database::Accessor::Predicate->new( %{$_} ) };
coerce 'Element', from 'HashRef', via {
...

in Database::Accessor::Types. With that change I go this error;


Attribute (predicates) does not pass the type constraint because: Validation failed for 'Predicate' with value ARRAY(0x424b214)

and to fix that I had to make a slight adjustment to the '_predicate_array_or_object' sub

..
else {
-- push( @{$objects}, $class->new( { predicates => [ $object ] } ) );
++ push( @{$objects}, $class->new( { predicates => $object } ) );
}


and the 'ArrayRefofConditions' sub

..
else {
--          push( @{$objects}, $class->new( { predicates => [$object] } ) );
++          push( @{$objects}, $class->new( { predicates => $object } ) );
..

in in Database::Accessor::Types, and I get by that error and get a hard fail in my test;

Not an ARRAY reference at D:\GitHub\database-accessor\lib/Database/Accessor.pm line 704.

as I still have this sort of call in my code

foreach my $predicate ( @{ $condition->predicates() } ) {

which is no longer valid as 'predicates' is now a singleton so I fixed that where needed

I had a few other things to clean up in the test code and test utilities as I used that now defunct 'predicates_count' in a few places and after a few runs I managed to squish all of those bugs and remove the odd test that no longer apply I had 33_conditions.t passing at 100%

Now to see what else I have buggered up. But that is another post.

IMG_2563a.jpg

Leave a comment

About byterock

user-pic Long time Perl guy, a few CPAN mods allot of work on DBD::Oracle and a few YAPC presentations