|Syntactic Confectionery Delight|
MooseX obscure error and importance of Unit Testingby greengaroo (Hermit)
|on Aug 15, 2012 at 14:51 UTC||Need Help??|
Let's meditate for a while. I just spend half a day trying to figure this out, and I finally resolved the problem easily, after creating a Unit Test script! If I had created the Unit Test script in the first place, I would have saved some very valuable time! That's why I want to share this with you, so maybe you will someday find yourself in a similar situation and decide to create a Unit Test script and save hours, unlike me!
Imagine I have two classes, using MooseX-Declare, one extends the other.
I also have a third class called Utils::File::SectionFactory. In a few words, what I am doing is simple, I have files in which I have sections, and inside sections I have entities. While reading the file, I use the Section Factory to create a Section object based on the section type, and I skip the rest of the story. Pretty simple. My instantiation method, from the Section Factory, looks like this:
Basically, what it does is using the right Class, creating an instance of that, and making sure it is a type of Section. Since Utils::File::Macro extends Utils::File::Section, if I create a Macro object, it will pass the validation as being also a Section object. I've done this hundreds of time, it always work.
But not this time! My code dies with:The Utils::File::Macro class is not a type of Section!
That's impossible! I say to myself. So after adding some prints here and there, I see that everything seems to be fine, but still, the Macro object is not considered to be a Section! Since I am running this from the SectionFactory Unit Test script, I decided to add this line just before the validation:Test::More::isa_ok( $obj, 'Utils::File::Section', '$obj' );
And I get:
Still, I don't understand what is going on! Now I am thinking that I have a problem in the Utils::File::Macro class, so i revise the syntax, line by line. Nothing wrong. But I have some doubts. I revise the documentation on ISA, just to make sure I am not imagining things. I know that the "isa" method comes from UNIVERSAL, so I go to CPAN and:...isa returns true if CLASS inherits from (or is itself) the name of the package TYPE or inherits from package TYPE.
Faith restored! So, after all this struggle, and several cups of coffee, I finally decide to create a simple Unit Test script for the Utils::File::Macro class:
This cannot do wrong! I will get to the bottom of this! Finally! The script throws:
The problem was that one of the Type Constraints, called 'MacrosEntity', used in Utils::File::Macro in the 'Add' method, was not defined properly in Utils::TypeConstraints!!! This was undetectable from the Section Factory Unit Test script! Even with years of experience with Perl, learning how to interpret obscure error message to be able to pinpoint the problems quickly, using Moose and MooseX will give you an extra level of challenge!
So the moral of the story, something I already knew but sometimes forget, Unit Test scripts should really test "units" or small bits of code. You should always test the smallest components first, then the more complex ones.
Now, your turn to meditate...
Take my advice. I don't use it anyway.