stevieb has asked for the wisdom of the Perl Monks concerning the following question:
Fellow ``I love Perl so much, I can taste what Larry is having for dinner when I eat'' monks:
I pretty much always write my code in OO style, so that I never have to fear pissing on an imported name. In fact, most of my 'objects' are an empty shell. Essentially, I've standardized my coding style so that all opts/params *must* be name-based within an href, and that each sub call *must* be prefixed with either $obj-> or Class->
My tests are normally written about two lines ahead of the actual code it will be testing. Normally, each t/N-sub.t contains numerous code blocks, each block contains a single test I want to perform against the sub, eg:
# t/22-date.t { # date() my $obj = ISP::Object->new(); my $ret = $obj->date(); isa_ok( $ret, 'DateTime', "calling date() with no params, return" +); } { # date() get param my $obj = ISP::Object->new(); my $ret = $obj->date({ get => 'month' }); ok( $ret =~ m{ \A \d{4}-\d{2} \z }xms, "called with get=>month wor +ks out ok" ); }
I'm sick of duplicating code, especially within tests. I have mitigated some of this by wrapping the instantiation code within an internal sub, but now I have to carry globals:
{ # add_trace() trivial _reset(); my $ret = $error->add_trace(); is ( $ret, 0, "add_trace() returns success (0) when successful" ); } { # add_trace() type _reset(); $error->add_trace(); my $type = reftype $error->stack(); is ( $type, 'ARRAY', "Error's stack trace is an array ref upon suc +cess" ); }
I've heard that there are some modules that provide an oo and procedural interface. Although I haven't looked at any said code, what I'd like to do is instantiate an object via any method the class offers, perform only the task that method is supposed to, and return the result without having to build everything.
I'm wondering if each method should just call something else other than new() if $self isn't a reference. A basic 'what I'm thinking' is this (compacted for brevity ;) :
# in the package sub new { my $class = shift; # suck in a config, bless and populate $self return $self; } sub one_call_only { return bless {}, shift; } sub attach { my $thing = shift; my $self = ( ref $thing ) ? $thing : $thing->one_call_only(); # do attach() stuff with $self, and...: return $self->{ sub_details }; }
So, instead of manually instantiating a new object in my tests within each block (or if I want to use one method within an object) without having to perform the elaborate and time-consuming work that new() performs, I'm looking for other options.
fwiw, just for the `what I've tried' aspect, this is a basic routine that seems very simple. However, if I call it against the full-blown object, there are significant sanity checks performed, along with other self-building. That extra overhead is very cumbersome when trying to write tests.
sub attach { my $self = shift; my $params = shift; if ( $params->{ filename } && -e $params->{ filename } ) { my $filename = $params->{ filename }; my $mime_type = mimetype( $filename ); push @{ $self->{ attachments } }, { Path => $filename, Type => $mime_type }; } return $self->{ attachments }; # aoh }
Feedback and pointers to other code very much welcome
Steve
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Saving keystrokes writing test suites
by chromatic (Archbishop) on Sep 03, 2010 at 04:39 UTC | |
|
Re: Saving keystrokes writing test suites
by JavaFan (Canon) on Sep 03, 2010 at 10:25 UTC | |
|
Re: Saving keystrokes writing test suites
by Xiong (Hermit) on Sep 06, 2010 at 22:03 UTC |