~ubuntu-branches/ubuntu/trusty/libtest-roo-perl/trusty-proposed

« back to all changes in this revision

Viewing changes to lib/Test/Roo.pm

  • Committer: Package Import Robot
  • Author(s): gregor herrmann
  • Date: 2014-01-14 19:25:11 UTC
  • Revision ID: package-import@ubuntu.com-20140114192511-9ycl4dc1zgamfnek
Tags: upstream-1.002
ImportĀ upstreamĀ versionĀ 1.002

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
use 5.008001;
 
2
use strictures;
 
3
 
 
4
package Test::Roo;
 
5
# ABSTRACT: Composable, reusable tests with roles and Moo
 
6
our $VERSION = '1.002'; # VERSION
 
7
 
 
8
use Test::More 0.96 import => [qw/subtest/];
 
9
 
 
10
use Sub::Install;
 
11
 
 
12
sub import {
 
13
    my ( $class, @args ) = @_;
 
14
    my $caller = caller;
 
15
    for my $sub (qw/test run_me/) {
 
16
        Sub::Install::install_sub( { into => $caller, code => $sub } );
 
17
    }
 
18
    strictures->import; # do this for Moo, since we load Moo in eval
 
19
    eval qq{
 
20
        package $caller;
 
21
        use Moo;
 
22
        extends 'Test::Roo::Class'
 
23
    };
 
24
    if (@args) {
 
25
        eval qq{ package $caller; use Test::More \@args };
 
26
    }
 
27
    else {
 
28
        eval qq{ package $caller; use Test::More };
 
29
    }
 
30
    die $@ if $@;
 
31
}
 
32
 
 
33
sub test {
 
34
    my ( $name, $code ) = @_;
 
35
    my $caller  = caller;
 
36
    my $subtest = sub {
 
37
        my $self = shift;
 
38
        subtest $name => sub { $self->each_test($code) }
 
39
    };
 
40
    eval qq{ package $caller; after _do_tests => \$subtest };
 
41
    die $@ if $@;
 
42
}
 
43
 
 
44
sub run_me {
 
45
    my $class = caller;
 
46
    $class->run_tests(@_);
 
47
}
 
48
 
 
49
1;
 
50
 
 
51
 
 
52
# vim: ts=4 sts=4 sw=4 et:
 
53
 
 
54
__END__
 
55
 
 
56
=pod
 
57
 
 
58
=encoding utf-8
 
59
 
 
60
=head1 NAME
 
61
 
 
62
Test::Roo - Composable, reusable tests with roles and Moo
 
63
 
 
64
=head1 VERSION
 
65
 
 
66
version 1.002
 
67
 
 
68
=head1 SYNOPSIS
 
69
 
 
70
Define test behaviors and required fixtures in a role:
 
71
 
 
72
    # t/lib/ObjectCreation.pm
 
73
 
 
74
    package ObjectCreation;
 
75
    use Test::Roo::Role;    # loads Moo::Role and Test::More
 
76
 
 
77
    requires 'class';       # we need this fixture
 
78
 
 
79
    test 'object creation' => sub {
 
80
        my $self = shift;
 
81
        require_ok( $self->class );
 
82
        my $obj  = new_ok( $self->class );
 
83
    };
 
84
 
 
85
    1;
 
86
 
 
87
Provide fixtures and run tests from the .t file:
 
88
 
 
89
    # t/test.t
 
90
 
 
91
    use Test::Roo; # loads Moo and Test::More
 
92
    use lib 't/lib';
 
93
 
 
94
    # provide the fixture
 
95
    has class => (
 
96
        is      => 'ro',
 
97
        default => sub { "Digest::MD5" },
 
98
    );
 
99
 
 
100
    # specify behaviors to test 
 
101
    with 'ObjectCreation';
 
102
 
 
103
    # give our subtests a pretty label
 
104
    sub _build_description { "Testing " . shift->class }
 
105
 
 
106
    # run the test with default fixture
 
107
    run_me;
 
108
 
 
109
    # run the test with different fixture
 
110
    run_me( { class => "Digest::SHA1" } );
 
111
 
 
112
    done_testing;
 
113
 
 
114
Result:
 
115
 
 
116
    $ prove -lv t
 
117
    t/test.t .. 
 
118
            ok 1 - require Digest::MD5;
 
119
            ok 2 - The object isa Digest::MD5
 
120
            1..2
 
121
        ok 1 - object creation
 
122
        1..1
 
123
    ok 1 - Testing Digest::MD5
 
124
            ok 1 - require Digest::SHA1;
 
125
            ok 2 - The object isa Digest::SHA1
 
126
            1..2
 
127
        ok 1 - object creation
 
128
        1..1
 
129
    ok 2 - Testing Digest::SHA1
 
130
    1..2
 
131
    ok
 
132
    All tests successful.
 
133
    Files=1, Tests=2,  0 wallclock secs ( 0.02 usr  0.01 sys +  0.06 cusr  0.00 csys =  0.09 CPU)
 
134
    Result: PASS
 
135
 
 
136
=head1 DESCRIPTION
 
137
 
 
138
This module allows you to compose L<Test::More> tests from roles.  It is
 
139
inspired by the excellent L<Test::Routine> module, but uses L<Moo> instead of
 
140
L<Moose>.  This gives most of the benefits without the need for L<Moose> as a
 
141
test dependency.
 
142
 
 
143
Test files are Moo classes.  You can define any needed test fixtures as Moo
 
144
attributes.  You define tests as method modifiers -- similar in concept to
 
145
C<subtest> in L<Test::More>, but your test method will be passed the test
 
146
object for access to fixture attributes.  You may compose any L<Moo::Role> into
 
147
your test to define attributes, require particular methods, or define tests.
 
148
 
 
149
This means that you can isolate test I<behaviors> into roles which require
 
150
certain test I<fixtures> in order to run.  Your main test file will provide the
 
151
fixtures and compose the roles to run.  This makes it easy to reuse test
 
152
behaviors.
 
153
 
 
154
For example, if you are creating tests for Awesome::Module, you could create
 
155
the test behaviors as Awesome::Module::Test::Role and distribute it with
 
156
your module.  If another distribution subclasses Awesome::Module, it can
 
157
compose the Awesome::Module::Test::Role behavior for its own tests.
 
158
 
 
159
No more copying and pasting tests from a super class!  Superclasses define and
 
160
share their tests.  Subclasses provide their own fixtures and run the tests.
 
161
 
 
162
=for Pod::Coverage add_methods_here
 
163
 
 
164
=head1 USAGE
 
165
 
 
166
Importing L<Test::Roo> also loads L<Moo> (which gives you L<strictures> with
 
167
fatal warnings and other goodies) and makes the current package a subclass
 
168
of L<Test::Roo::Class>.
 
169
 
 
170
Importing also loads L<Test::More>.  No test plan is used.  The C<done_testing>
 
171
function must be used at the end of every test file.  Any import arguments are
 
172
passed through to Test::More's C<import> method.
 
173
 
 
174
See also L<Test::Roo::Role> for test role usage.
 
175
 
 
176
=head2 Creating fixtures
 
177
 
 
178
You can create fixtures with normal Moo syntax.  You can even make them lazy if
 
179
you want:
 
180
 
 
181
    has fixture => (
 
182
        is => 'lazy'
 
183
    );
 
184
 
 
185
    sub _build_fixture { ... }
 
186
 
 
187
This becomes really useful with L<Test::Roo::Role>.  A role could define the
 
188
attribute and require the builder method to be provided by the main test class.
 
189
 
 
190
=head2 Composing test roles
 
191
 
 
192
You can use roles to define units of test behavior and then compose them into
 
193
your test class using the C<with> function.  Test roles may define attributes,
 
194
declare tests, require certain methods and anything else you can regularly do
 
195
with roles.
 
196
 
 
197
    use Test::Roo;
 
198
 
 
199
    with 'MyTestRole1', 'MyTestRole2';
 
200
 
 
201
See L<Test::Roo::Role> and the L<Test::Roo::Cookbook> for details and
 
202
examples.
 
203
 
 
204
=head2 Setup and teardown
 
205
 
 
206
You can add method modifiers around the C<setup> and C<teardown> methods and
 
207
these will be run before tests begin and after tests finish (respectively).
 
208
 
 
209
    before  setup     => sub { ... };
 
210
 
 
211
    after   teardown  => sub { ... };
 
212
 
 
213
You can also add method modifiers around C<each_test>, which will be
 
214
run before and after B<every> individual test.  You could use these to
 
215
prepare or reset a fixture.
 
216
 
 
217
    has fixture => ( is => 'lazy, clearer => 1, predicate => 1 );
 
218
 
 
219
    after  each_test => sub { shift->clear_fixture };
 
220
 
 
221
Roles may also modify C<setup>, C<teardown>, and C<each_test>, so the order
 
222
that modifiers will be called will depend on when roles are composed.  Be
 
223
careful with C<each_test>, though, because the global effect may make
 
224
composition more fragile.
 
225
 
 
226
You can call test functions in modifiers. For example, you could
 
227
confirm that something has been set up or cleaned up.
 
228
 
 
229
    before each_test => sub { ok( ! shift->has_fixture ) };
 
230
 
 
231
=head2 Running tests
 
232
 
 
233
The simplest way to use L<Test::Roo> with a single F<.t> file is to let the
 
234
C<main> package be the test class and call C<run_me> in it:
 
235
 
 
236
    # t/test.t
 
237
    use Test::Roo; # loads Moo and Test::More
 
238
 
 
239
    has class => (
 
240
        is      => 'ro',
 
241
        default => sub { "Digest::MD5" },
 
242
    );
 
243
 
 
244
    test 'load class' => sub {
 
245
        my $self = shift;
 
246
        require_ok( $self->class );
 
247
    }
 
248
 
 
249
    run_me;
 
250
    done_testing;
 
251
 
 
252
Calling C<< run_me(@args) >> is equivalent to calling
 
253
C<< __PACKAGE__->run_tests(@args) >> and runs tests for the current package.
 
254
 
 
255
You may specify an optional description or hash reference of constructor
 
256
arguments to customize the test object:
 
257
 
 
258
    run_me( "load MD5" );
 
259
    run_me( { class => "Digest::MD5" } );
 
260
    run_me( "load MD5", { class => "Digest::MD5" } );
 
261
 
 
262
See L<Test::Roo::Class> for more about the C<run_tests> method.
 
263
 
 
264
Alternatively, you can create a separate package (in the test file or in a
 
265
separate F<.pm> file) and run tests explicitly on that class.
 
266
 
 
267
    # t/test.t
 
268
    package MyTest;
 
269
    use Test::Roo;
 
270
 
 
271
    use lib 't/lib';
 
272
 
 
273
    has class => (
 
274
        is       => 'ro',
 
275
        required => 1,
 
276
    );
 
277
 
 
278
    with 'MyTestRole';
 
279
 
 
280
    package main;
 
281
    use strictures;
 
282
    use Test::More;
 
283
 
 
284
    for my $c ( qw/Digest::MD5 Digest::SHA/ ) {
 
285
        MyTest->run_tests("Testing $c", { class => $c } );
 
286
    }
 
287
 
 
288
    done_testing;
 
289
 
 
290
=head1 EXPORTED FUNCTIONS
 
291
 
 
292
Loading L<Test::Roo> exports subroutines into the calling package to declare
 
293
and run tests.
 
294
 
 
295
=head2 test
 
296
 
 
297
    test $label => sub { ... };
 
298
 
 
299
The C<test> function adds a subtest.  The code reference will be called with
 
300
the test object as its only argument.
 
301
 
 
302
Tests are run in the order declared, so the order of tests from roles will
 
303
depend on when they are composed relative to other test declarations.
 
304
 
 
305
=head2 run_me
 
306
 
 
307
    run_me;
 
308
    run_me( $description );
 
309
    run_me( $init_args   );
 
310
    run_me( $description, $init_args );
 
311
 
 
312
The C<run_me> function calls the C<run_tests> method on the current package
 
313
and passes all arguments to that method.  It takes a description and/or
 
314
a hash reference of constructor arguments.
 
315
 
 
316
=head1 DIFFERENCES FROM TEST::ROUTINE
 
317
 
 
318
While this module was inspired by L<Test::Routine>, it is not a drop-in
 
319
replacement.  Here is an overview of major differences:
 
320
 
 
321
=over 4
 
322
 
 
323
=item *
 
324
 
 
325
L<Test::Roo> uses L<Moo>; L<Test::Routine> uses L<Moose>
 
326
 
 
327
=item *
 
328
 
 
329
Loading L<Test::Roo> makes the importing package a class; in L<Test::Routine> it becomes a role
 
330
 
 
331
=item *
 
332
 
 
333
Loading L<Test::Roo> loads L<Test::More>; L<Test::Routine> does not
 
334
 
 
335
=item *
 
336
 
 
337
In L<Test::Roo>, C<run_test> is a method; in L<Test::Routine> it is a function and takes arguments in a different order
 
338
 
 
339
=item *
 
340
 
 
341
In L<Test::Roo>, all role composition must be explicit using C<with>; in L<Test::Routine>, the C<run_tests> command can also compose roles
 
342
 
 
343
=item *
 
344
 
 
345
In L<Test::Roo>, test blocks become method modifiers hooked on an empty method; in L<Test::Routine>, they become methods run via introspection
 
346
 
 
347
=item *
 
348
 
 
349
In L<Test::Roo>, setup and teardown are done by modifying C<setup> and C<teardown> methods; in L<Test::Routine> they are done by modifying C<run_test>
 
350
 
 
351
=back
 
352
 
 
353
=for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan
 
354
 
 
355
=head1 SUPPORT
 
356
 
 
357
=head2 Bugs / Feature Requests
 
358
 
 
359
Please report any bugs or feature requests through the issue tracker
 
360
at L<https://github.com/dagolden/Test-Roo/issues>.
 
361
You will be notified automatically of any progress on your issue.
 
362
 
 
363
=head2 Source Code
 
364
 
 
365
This is open source software.  The code repository is available for
 
366
public review and contribution under the terms of the license.
 
367
 
 
368
L<https://github.com/dagolden/Test-Roo>
 
369
 
 
370
  git clone https://github.com/dagolden/Test-Roo.git
 
371
 
 
372
=head1 AUTHOR
 
373
 
 
374
David Golden <dagolden@cpan.org>
 
375
 
 
376
=head1 CONTRIBUTOR
 
377
 
 
378
Diab Jerius <djerius@gmail.com>
 
379
 
 
380
=head1 COPYRIGHT AND LICENSE
 
381
 
 
382
This software is Copyright (c) 2013 by David Golden.
 
383
 
 
384
This is free software, licensed under:
 
385
 
 
386
  The Apache License, Version 2.0, January 2004
 
387
 
 
388
=cut