NAME
Test::Class::Sugar - Helper syntax for writing Test::Class tests
SYNOPSIS
use Test::Class::Sugar;
testclass exercises Person {
# Test::Most has been magically included
startup >> 1 {
use_ok $test->subject;
}
test autonaming {
is ref($test), 'Test::Person';
}
test the naming of parts {
is $test->current_method, 'test_the_naming_of_parts';
}
test multiple assertions >> 2 {
is ref($test), 'Test::Person';
is $test->current_method, 'test_multiple_assertions';
}
}
Test::Class->runtests;
DESCRIPTION
Test::Class::Sugar provides a new syntax for setting up your Test::Class based tests. The idea is that we bundle up all the tedious boilerplate involved in writing a class in favour of getting to the meat of what you're testing. We made warranted assumptions about what you want to do, and we do them for you. So, when you write
testclass exercises Person {
...
}
What Perl sees, after Test::Class::Sugar has done its work, is roughly:
{
package Test::Person;
use base qw/Test::Class/;
use strict; use warnings;
require Person;
sub subject { 'Person' };
...
}
Some of the assumptions we made are overrideable, others aren't. Yet. Most of them will be though. See "Changing Assumptions" for details
Why you shouldn't use Test::Class::Sugar
Test::Class::Sugar is very new, pretty untested and is inadvertently hostile to you if you confuse its parser. Don't use it if you want to live.
Why you should use Test::Class::Sugar
But it's so shiny. Test::Class::Sugar was written to scratch an itch I had when writing some tests for a MooseX::Declare based module. Switching from the implementation code to the test code was like shifting from fifth to first gear in one fell swoop. Not fun. This is my attempt to sprinkle some Devel::Declare
magic dust over the testing experience.
Bear this in mind
Test::Class::Sugar is not a source filter
I know it looks like a source filter in the right light, but it isn't. Source filters fall down because only perl can parse Perl, so it's easy to confuse them. Devel::Declare based modules work by letting perl parse Perl until it comes across a new keyword, at which point it temporarily hands parsing duty over to a new parser which has the job of parsing the little language introduced by the keyword, turning it into real Perl, and handing the responsibility for parsing that back to Perl. Obviously, it's still possible for that to screw things up royally, but there are fewer opportunities to fuck up.
We now return you to your regularly schedule documentation.
SYNTAX
Essentially, Test::Class::Sugar adds some new keywords to perl. Here's what they do, and what they expect.
- testclass
-
testclass NAME? ( exercises CLASS | extends CLASS (, CLASS)* | uses HELPER (, HELPER)* )*
Where NAME is is an optional test class name - the sort of thing you're used to writing after
package
. You don't have to name yourtestclass
, but if you don't supply a name, you MUST supply an exercises clause.- exercises CLASS
-
You can supply at most one
exercises
clause. This specifies the class under test. We use it to autoname the class if you haven't provided a NAME of your own (the default name of the class would beTest::<CLASS>
). Also, if you supply an exercises clause, the class will be autorequired and your test class will have asubject
helper method, which will return the name of the class under test. - extends CLASS (, CLASS)*
-
Sometimes, you don't want to inherit directly from Test::Class. If that's the case, add an
extends
clause, and your worries will be over. The extends clause supports, but emphatically does not encourage, multiple inheritance. Friends don't let friends do multiple inheritance, but Test::Class::Sugar's not a friend, it's a robot servant which will provide you with more than enough rope. - uses HELPER (, HELPER)*
-
Ah, the glory that is the
uses
clause. If you don't provide a uses clause, Test::Class::Sugar will assume that you want to use Test::Most as your testing only testing helper library. If you would rather use, say, Test::More then you can do:testclass ExampleTest uses -More {...}
Hang on,
-More
, what's that about? It's a simple shortcut. Instead of making you writeuses Test::This, Test::That, Test::TheOther
, you can writeuses -This, -That, -TheOther
and we'll expand the-
intoTest::
and do the right thing.Note that, if you need to do anything special in the way of import arguments, you should do the
use
yourself. We're all about the 80:20 rule here.
- test
-
test WORD ( WORD )* (>> PLAN) { ... }
I may be fooling myself, but I hope its obvious what this does. Here's a few examples to show you what's happening:
test with multiple subtests >> 3 {...} test with no_plan >> no_plan {...} test 'a complicated description with "symbols" in it' {...}
Gets translated to:
sub test_with_multiple_subtests : Test(3) {...} sub test_with_no_plan : Test(no_plan) {...} sub a_complicated_description_with_symbols_in_it : Test {...}
See "Test" in Test::Class for details of
PLAN
's semantics.
Lifecycle Methods
- startup
- setup
- teardown
- shutdown
-
These lifecycle helpers work in pretty much the same way as "test", but with the added wrinkle that, if you don't supply a name, they generate method names derived from the name of the test class and the name of the helper, so, for instance:
testclass Test::Lifecycle::Autonaming { setup { ... } }
is equivalent to writing:
testclass Test::Lifecycle::Autonaming { setup 'setup_Test_Lifecycle_Autonaming' {...} }
Other than that, the lifecycle helpers behave pretty much as described in Test::Class. In particular, you can still give them names, so
testclass { setup with a name {...} }
works just fine.
Changing Assumptions
There are several aspects of Test::Class::Sugar's policy that you may disagree with. If you do, you can adjust them by passing a 'defaults' hash at use time. For example:
use Test::Class::Sugar defaults => { prefix => TestSuite };
Here's a list of the possible default settings and what they affect.
- prefix
-
Changes the prefix used for autogenerating test class names from
Test::
to whatever you specify, so:use Test::Class::Sugar defaults => { prefix => TestSuite }; testclass exercises Something { ... }
will build a test class called
TestSuite::Something
- test_instance
-
COMING SOON
Prefer
$self
to$test
in your test methods? Then thetest_instance
default is your friend. Just douse Test::Class::Sugar defaults => { test_instance => '$self' }
and all manner of things shall be well.
- uses
-
COMING SOON, BUT PROBABLY LATER THAN
test_instance
Bored of adding the same old
uses
clause to your every testclass? Fix it at use time like so:use Test::Class::Sugar defaults => { uses => [qw/Test::More Moose/] };
DIAGNOSTICS
Right now, Test::Class::Sugar's diagnostics range from the confusing to the downright misleading. Expect progress on this in the future, tuit supply permitting.
Patches welcome.
BUGS AND LIMITATIONS
Known bugs
- Screwy line numbers
-
Test::Class::Sugar can screw up the accord between the line perl thinks some code is on and the line the code is actually on. This makes debugging test classes harder than it should be. Our error reporting is bad enough already without making things worse.
Unknown bugs
There's bound to be some.
Patches welcome.
Please report any bugs or feature requests to me. It's unlikely you'll get any response if you use http://rt.cpan.org though. Your best course of action is to fork the project http://www.github.com/pdcawley/test-class-sugar, write at least one failing test (Write something in testclass
form that should work, but doesn't. If you can arrange for it to fail gracefully, then please do, but if all you do is write something that blows up spectacularly, that's good too. Failing/exploding tests are like manna to a maintenance programmer.
AUTHOR
Piers Cawley <pdcawley@bofh.org.uk>
LICENCE AND COPYRIGHT
Copyright (c) 2009, Piers Cawley <pdcawley@bofh.org.uk>
. All rights reserved.
This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.
DISCLAIMER OF WARRANTY
BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
2 POD Errors
The following errors were encountered while parsing the POD:
- Around line 283:
You forgot a '=back' before '=head2'
- Around line 285:
'=item' outside of any '=over'