views:

183

answers:

4

I want to start strictly doing Test-Driven-Development. However, I was wondering how much I should test methods generated by Moose and MooseX::FollowPBP. For example, I have the following class:

package Neu::Series;
use Moose;
use MooseX::FollowPBP;

use File::Find::Wanted;

has 'file_regex' => (
    isa=>'RegexpRef',
    is=>'rw',
    default => sub{
                 qr{
                   [A-Z]       #Uppercase letter
                   [a-zA-Z]*   #any letter, any number of times
                   [-]         #dash
                   (           #open capturing parenthesis
                   [0-9]
                   [0-9]
                   [0-9]
                   [0-9]
                   [a-zA-Z]?   #any letter, optional
                   )           #close capturing parenthesis
               }xms;
           },
);


has 'top_dir' => (
    isa=>'Str',
    is=>'rw',
);


has 'access' =>(
    isa=>'Neu::Access',
    is=>'ro',
    required=>1,

);

1;

My current test script is:

use strict;
use warnings;
use Test::More tests => 8;
use Neu::Access;

BEGIN{ use_ok('Neu::Series'); }

can_ok( 'Neu::Series', 'new');
can_ok( 'Neu::Series', 'set_file_regex');
can_ok( 'Neu::Series', 'get_file_regex');
can_ok( 'Neu::Series', 'set_top_dir');
can_ok( 'Neu::Series', 'get_top_dir');
can_ok( 'Neu::Series', 'get_access');

my $access = Neu::Access->new(dsn => 'test');
my $series_worker = Neu::Series->new(access => $access);

isa_ok($series_worker, 'Neu::Series');

Is this enough or too-much testing? (That is, besides the obviously missing tests for the regex).

I thought I saw a web page or another post about this somewhere, but I haven't been able to find it today.

+2  A: 

Checking that all accessors were generated correctly is fine... however there are other things you could test at a slight higher level, e.g. why not test that the attributes were generated properly?

use Test::Deep;
my @attrs = Neu::Series->meta->get_all_attributes;
cmp_deeply( [ map { $_->name } @attrs ], superbagof(qw(file_regex top_dir access)));
Ether
Thanks for introducing me to `Test::Deep`! After reading your answer, I went and looked at the documentation and am really impressed with it. I was also impressed that `Test::Deep::NoTest` will allow you to do all of the same comparisons in a non-test situation.
molecules
I like your idea of querying the meta class for testing purposes. It gives me pause when I consider that this makes the tests themselves dependent on Moose, what happens if I choose to abandon Moose for my project (fat chance of that)? Is it better to have black box tests that verify a particular method is present and behaves properly (at the cost more complex testing), or is it better to use meta class info to introspect the class and verify the specification directly?
daotoad
@daotoad: I guess it's a question of whether you think you might move away from Moose, and how much you trust each Moose release to be tested thoroughly. It's quite common for various refactorings to necessitate changing the unit tests, and since the Moose installation process is pretty solid, IMHO I'd just test the existence of the attributes and then go on to test the actual implementation of your class (the application logic that doesn't involve Moose). I use meta-specific tests in my $work when testing complicated role composition, where it's quite possible that an attribute is missing.
Ether
+1  A: 

I'd focus on testing my specification. Did I tell Moose what I wanted it to do correctly?

To this end, I'd start with the following tests:

  • Verify that read/write attributes have both an accessor and a mutator.
  • Verify that read only attributes have an accessor and no mutator.
  • Test any type constraints and coercions. Verify that only acceptable values can be set. If an attribute sIf you expect VII to be seen as a Str and coerced into an Int as 7, test that it does.
daotoad
Thanks for your answer. You're right that I should test *everything* that I could possibly get wrong myself.
molecules
+5  A: 

There's really no point in testing that the accessors were generated correctly. If they're not, you'll find out very quickly, because any real tests you write will fail.

Moose itself tests that accessors are generated correctly, that Moose-using classes get a constructor, and so on. One of the points of using dependencies is so that you can focus on writing and testing your application, not helper code.

I do agree with daotoad, it's probably worth testing constraints and coercions that you write yourself.

Dave Rolsky
That's wonderful! Thanks to you and the rest of the Moose team.
molecules
I agree that there is no point in writing tests that recapitulate Moose's exhaustive test set, but I stand by my suggestion to verify accessors and mutators. I trust Moose to do what I tell it to do--Moose has always done exactly what I wrote. However, I don't trust myself to tell Moose what I want it to do. It is pretty easy to put `rw` in an attribute when you really want `ro`. These tests should be as simple as possible--they test the spec, not the functionality.
daotoad
I wrote a [blog entry](http://blog.urth.org/2010/02/the-purpose-of-automated-tests.html) about this topic.
Dave Rolsky
You're not testing that Moose generated accessors correctly. You're testing that you're maintaining the same interface to the outside world. Just because a method is currently implemented as a Moose accessor doesn't mean that it will continue being implemented that way forever.http://elliotlovesperl.com/2010/02/16/test-moose-accessors-hell-yes/
Elliot Shank
If you stop using Moose and switch to writing all your own constructors and accessors, then there are two paths. If you do it all by hand (you're an idiot), then yes, tests like the above might be valuable.If you switch to some other framework, the same argument applies. Don't test your dependencies.
Dave Rolsky
Always test your whole interface without caring who created it. I violently disagree with Dave on this one for all the reasons Elliot and daotoad already outlined.
brian d foy
Sorry about changing the accepted answer. After trying it out both ways, I'm much more comfortable with explicitly testing the interface.
molecules
+1  A: 

Thank you Dave, daotoad, Ether, Elliot, and brian. From reading your answers, comments, and blogs, there seem to be two salient points:

(1) No testing is needed to make sure Moose does what it is supposed to do. I think everyone agrees on this point.

(2) Testing Moose-generated methods is appropriate for establishing, testing, and maintaining your interface. Most agree on this point.

Again, thanks to everyone for your input.

EDIT:

This is just a community-wiki summary. Please read the individual answers and comments.

molecules