You might find Test::Deep right up your alley! On Fri, Sep 9, 2016 at 6:34 PM, Sam Kington <s...@illuminated.co.uk> wrote:
> Hi, > > At $WORK we have an extensive test suite that we’ve built up over the > years, with loads of convenience methods for calling e.g. Dancer endpoints > and checking returned data structures against what we expect. One of our > dev team recently left for pastures new, and would like to carry on using > these tools. How should I best extract this functionality into a proper > CPAN distribution (ideally using Test2)? > > At its most elaborate, our current test code lets you say e.g. > > # Assume $self->state('location_id') has been set previously > $self->test( > title => 'Create a properly megalithic structure', > call => [ > POST => '/location/:location_id/build', > { > author => 'Wally Wallington', > structures => [ > { > type => 'dolmen', > material => 'concrete', > } > ] > } > ], > expect => { > http_code => HTTP_CREATED, > sql_count => 12, > data => { > location_id => $self->state('location_id'), > build_id => qr{^ (?<build_id> BUILD \d+ ) $}x, > built => $self->true, > author => $self->meh, # It's OK if they call him Idiot. > structures => [ > { > _hashref_contains => { > structure_id => qr{^ (?<structure_id> STRUCT \d+ ) > $}x, > type => 'dolmen', > material => 'concrete', > > # There's probably stuff about where the dolmen > # was erected but we ignore that for the purpose > # of this test. > } > } > ] > } > } > ); > > # $self->state('build_id') got set by the named capture in the regex above. > $self->test( > title => 'Turn it to gold because lol', > call => [ > PATCH => '/location/:location_id/build/:build_id/structure/: > structure_id', > { material => 'gold' } > ], > expect => { > # The same as saying data => { _hashref_contains => { material => > 'gold' } } > data_contains => { > material => 'gold' > } > } > ); > > And if anything doesn’t quite match, it tries to show you what did and > didn’t match. > > The stuff in call gets passed to e.g. Dancer::Test::dancer_response or > treated as a method call, depending on the invocation. As we share a common > process with the code being called and tested, we can also monitor the > database calls being made via DBIx::Class, and there’s some fiendish code > for tracking, diagnosing and correcting test errors regarding the number of > distinct database queries being made. > > These are all nice-to-haves rather than something that’s inherent to the > design of this testing code. What’s really useful, and what my ex-colleague > is hankering after, is a couple of things: > > (A) To say, flexibly, “I want a data structure that looks like this”, and > to be able to say (1) this field must look exactly like this, (2) this > field should look like this, and remember it, (3) this field should exist, > but I don’t care what its value is, and (4) there might be additional > fields but I don’t care about them for the purpose of this test. > > (B) To maintain a collection of placeholders that can be updated by tests > and used by subsequent tests. > > I haven’t looked recently at the Test:: infrastructure, so for all I know > we may have replicated functionality that we’d missed a few years ago when > we started coding. > > But if this functionality is new and useful, how should I implement it? > > Sam > -- > Website: http://www.illuminated.co.uk/ > >