Tip-toe in the Moose Patch
Well my last post I explored a little bit of the shinny new Test::Moose::More by adding a few tests to my Acme::Moose class.
I left off with the idea that I could use a test that tells me that I have extra attributes in my 'class'. Not being much afraid to muck about in source code I had a look in 'Test::Moose::More' to see what would be involved in creating such a test.
Well after a few min of poking about I settled on just extending the 'validate_thing' sub by adding in a new Key, 'no_extra_attributes', on the attributes hash. If this key is present then my little test will kick in and report any attributes that are not on the list passed in via the 'attributes' key.
Here is the patch
if ($args{no_extra_attributes}) {
local $THING_NAME = "${thing}";
my @from_meta = $thing->meta->get_attribute_list();
my @new_from_attr= (@{Data::OptList::mkopt($args{attributes} || [])});
if (scalar(@from_meta) == scalar(@new_from_attr)){
ok(1==1, "$THING_NAME has no extra attributes");
}
else {
my %new_from_attr = map {$_->[0]=>1} @new_from_attr;
for my $attribute (@from_meta){
unless(exists($new_from_attr{$attribute})){
$tb->subtest("[subtest] checking $THING_NAME" => sub {
ok(1==0, "$THING_NAME has extra attribute $attribute");
});
}
}
}
}
And if I add in this into ACME::Moose
has [ 'hate_llamas', 'foodage','happiness','tired']=> (is=>'rw',default=>0,isa=>'Int',init_arg=>"");
no Moose;
and run my new test
ok 27 - Acme::Moose has an attribute named tired
not ok 1 - Acme::Moose=HASH(0x1a4124c) has extra attribute hate_llamas
1..1
not ok 28 - [subtest] checking Acme::Moose=HASH(0x1a4124c)
Dubious, test returned 1 (wstat 256, 0x100)
great reports that I have something extra.
I then just did a quick fork on github and added in my change and wait for the sparks to fly.
I will have to send an email out on it but I think Github does that anyway and I am pretty sure the maintainer reads this blog so he or she will soon find out about it.
Hopefully they do not treat it as this Moose does.
Well in that email I should give reasoning for the test. I would think it goes likes this. If the test fails that means I have extra stuff in my class and that would be the result of
- My tests are out of date or.
- An attribute is present that should not be there.
Either way a change must be made to my code or my tests.
Doing this kind of patch is always problematic, as one has to carefully look at the code you are going to patch and sometimes if it is newish code you have to guess on the intentions of the original programmer.
In this case I had to make sure that I mimicked how he typed out the 'attributes' key. As what was going on here
for my $attribute (@{Data::OptList::mkopt($args{attributes} || [])}) {
my ($name, $opts) = @$attribute;
has_attribute_ok($thing, $name);
it is clear from the code that both an array-ref of scalars or an array-ref of hash-refs are allowed even though though the documentation just says an array ref
validate_class $thing => (attributes => [ ... ],
At this stage it is just a suggestion but I do see it having potential that we could just have a key 'no_extra' that would check for anything that in not on one of the arrays passed into the 'validate_thing' test.
Oh well lets see what happens.
Leave a comment