CPANifying our test framework - or parts of it
[email protected] (Sam Kington) Sat, 10 Sep 2016 03:34:02 +0200
| Newsgroups | perl.qa |
|---|---|
| Message-ID | <[email protected]> |
Hi,
At $WORK we have an extensive test suite that we=E2=80=99ve 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 =3D> 'Create a properly megalithic structure',
call =3D> [
POST =3D> '/location/:location_id/build',
{
author =3D> 'Wally Wallington',
structures =3D> [
{
type =3D> 'dolmen',
material =3D> 'concrete',
}
]
}
],
expect =3D> {
http_code =3D> HTTP_CREATED,
sql_count =3D> 12,
data =3D> {
location_id =3D> $self->state('location_id'),
build_id =3D> qr{^ (?<build_id> BUILD \d+ ) $}x,
built =3D> $self->true,
author =3D> $self->meh, # It's OK if they call him =
Idiot.
structures =3D> [
{
_hashref_contains =3D> {
structure_id =3D> qr{^ (?<structure_id> STRUCT =
\d+ ) $}x,
type =3D> 'dolmen',
material =3D> '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 =3D> 'Turn it to gold because lol',
call =3D> [
PATCH =3D> =
'/location/:location_id/build/:build_id/structure/:structure_id',
{ material =3D> 'gold' }
],
expect =3D> {
# The same as saying data =3D> { _hashref_contains =3D> { =
material =3D> 'gold' } }
data_contains =3D> {
material =3D> 'gold'
}
}
);
And if anything doesn=E2=80=99t quite match, it tries to show you what =
did and didn=E2=80=99t 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=E2=80=99s=
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=E2=80=99s =
inherent to the design of this testing code. What=E2=80=99s really =
useful, and what my ex-colleague is hankering after, is a couple of =
things:
(A) To say, flexibly, =E2=80=9CI want a data structure that looks like =
this=E2=80=9D, 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=E2=80=99t care what its value is, and =
(4) there might be additional fields but I don=E2=80=99t 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=E2=80=99t looked recently at the Test:: infrastructure, so for =
all I know we may have replicated functionality that we=E2=80=99d missed =
a few years ago when we started coding.
But if this functionality is new and useful, how should I implement it?
Sam
--=20
Website: http://www.illuminated.co.uk/