File Coverage

blib/lib/Test/Class/Most.pm
Criterion Covered Total %
statement 81 84 96.4
branch 16 22 72.7
condition 5 9 55.5
subroutine 19 19 100.0
pod 0 1 0.0
total 121 135 89.6


line stmt bran cond sub pod time code
1             package Test::Class::Most;
2              
3 1     1   51333 use warnings;
  1         1  
  1         31  
4 1     1   6 use strict;
  1         2  
  1         33  
5 1     1   4 use Test::Class;
  1         6  
  1         18  
6 1     1   9 use Carp 'croak';
  1         1  
  1         1055  
7              
8             =head1 NAME
9              
10             Test::Class::Most - Test Classes the easy way
11              
12             =head1 VERSION
13              
14             Version 0.08
15              
16             =cut
17              
18             our $VERSION = '0.08';
19             $VERSION = eval $VERSION;
20              
21             =head1 SYNOPSIS
22              
23             Instead of this:
24              
25             use strict;
26             use warnings;
27             use Test::Exception 0.88;
28             use Test::Differences 0.500;
29             use Test::Deep 0.106;
30             use Test::Warn 0.11;
31             use Test::More 0.88;
32              
33             use parent 'My::Test::Class';
34              
35             sub some_test : Tests { ... }
36              
37             You type this:
38              
39             use Test::Class::Most parent => 'My::Test::Class';
40              
41             sub some_test : Tests { ... }
42              
43             =head1 DESCRIPTION
44              
45             When people write test classes with the excellent C, you often
46             see the following at the top of the code:
47              
48             package Some::Test::Class;
49              
50             use strict;
51             use warnings;
52             use base 'My::Test::Class';
53             use Test::More;
54             use Test::Exception;
55              
56             # and then the tests ...
57              
58             That's a lot of boilerplate and I don't like boilerplate. So now you can do
59             this:
60              
61             use Test::Class::Most parent => 'My::Test::Class';
62              
63             That automatically imports L and L for you. It also gives
64             you all of the testing goodness from L.
65              
66             =head1 CREATING YOUR OWN BASE CLASS
67              
68             You probably want to create your own base class for testing. To do this,
69             simply specify no import list:
70              
71             package My::Test::Class;
72             use Test::Class::Most; # we now inherit from Test::Class
73              
74             INIT { Test::Class->runtests }
75              
76             1;
77              
78             And then your other classes inherit as normal (well, the way we do it):
79              
80             package Tests::For::Foo;
81             use Test::Class::Most parent => 'My::Test::Class';
82              
83             And you can inherit from those other classes, too:
84              
85             package Tests::For::Foo::Child;
86             use Test::Class::Most parent => 'Tests::For::Foo';
87              
88             Of course, it's quite possible that you're a fan of multiple inheritance, so
89             you can do that, too (I was I tempted to not allow this, but I
90             figured I shouldn't force too many of my personal beliefs on you):
91              
92             package Tests::For::ISuckAtOO;
93             use Test::Class::Most parent => [qw/
94             Tests::For::Foo
95             Tests::For::Bar
96             Some::Other::Class::For::Increased::Stupidity
97             /];
98              
99             As a side note, it's recommended that even if you don't need test control
100             methods in your base class, put stubs in there:
101              
102             package My::Test::Class;
103             use Test::Class::Most; # we now inherit from Test::Class
104              
105             INIT { Test::Class->runtests }
106              
107             sub startup : Tests(startup) {}
108             sub setup : Tests(setup) {}
109             sub teardown : Tests(teardown) {}
110             sub shutdown : Tests(shutdown) {}
111              
112             1;
113              
114             This allows developers to I be able to safely call parent test control
115             methods rather than wonder if they are there:
116              
117             package Tests::For::Customer;
118             use Test::Class::Most parent => 'My::Test::Class';
119              
120             sub setup : Tests(setup) {
121             my $test = shift;
122             $test->next::method; # safe due to stub in base class
123             ...
124             }
125              
126             =head1 ATTRIBUTES
127              
128             You can also specify "attributes" which are merely very simple getter/setters.
129              
130             use Test::Class::Most
131             parent => 'My::Test::Class',
132             attributes => [qw/customer items/],
133             is_abstract => 1;
134              
135             sub setup : Tests(setup) {
136             my $test = shift;
137             $test->SUPER::setup;
138             $test->customer( ... );
139             $test->items( ... );
140             }
141              
142             sub some_tests : Tests {
143             my $test = shift;
144             my $customer = $test->customer;
145             ...
146             }
147              
148             If called with no arguments, returns the current value. If called with one
149             argument, sets that argument as the current value. If called with more than
150             one argument, it croaks.
151              
152             =head1 ABSTRACT CLASSES
153              
154             You may pass an optional C parameter in the import list. It takes
155             a boolean value. This value is advisory only and is not inherited. It defaults
156             to false if not provided.
157              
158             Sometimes you want to identify a test class as "abstract". It may have a bunch
159             of tests, but those should only run for its subclasses. You can pass
160             C< 1>> in the import list. Then, to test if a given class or
161             instance of that class is "abstract":
162              
163             sub dont_run_in_abstract_base_class : Tests {
164             my $test = shift;
165             return if Test::Class::Most->is_abstract($test);
166             ...
167             }
168              
169             Note that C is strictly B. You are expected
170             (required) to check the value yourself and take appropriate action.
171              
172             We recommend adding the following method to your base class:
173              
174             sub is_abstract {
175             my $test = shift;
176             return Test::Class::Most->is_abstract($test);
177             }
178              
179             And later in a subclass:
180              
181             if ( $test->is_abstract ) { ... }
182              
183             =head1 EXPORT
184              
185             All functions from L are automatically exported into your
186             namespace.
187              
188             =cut
189              
190             {
191             my %IS_ABSTRACT;
192              
193             sub is_abstract {
194 8     8 0 12675 my ( undef, $proto ) = @_;
195 8   66     33 my $test_class = ref $proto || $proto;
196 8         33 return $IS_ABSTRACT{$test_class};
197             }
198              
199             sub import {
200 4     4   4754 my ( $class, %args ) = @_;
201 4         9 my $caller = caller;
202 1     1   884 eval "package $caller; use Test::Most;";
  1     1   24030  
  1     1   7  
  1     1   7  
  1         1  
  1         8  
  1         5  
  1         2  
  1         5  
  1         5  
  1         2  
  1         5  
  4         233  
203 4 50       48004 croak($@) if $@;
204 4         51 warnings->import;
205 4         53 strict->import;
206 4 100       28 if ( my $parent = delete $args{parent} ) {
207 3 50 66     17 if ( ref $parent && 'ARRAY' ne ref $parent ) {
208 0         0 croak(
209             "Argument to 'parent' must be a classname or array of classnames, not ($parent)"
210             );
211             }
212 3 100       10 $parent = [$parent] unless ref $parent;
213 3         8 foreach my $p (@$parent) {
214 1     1   6 eval "use $p";
  1     1   3  
  1     1   21  
  1     1   5  
  1         1  
  1         17  
  1         6  
  1         2  
  1         11  
  1         4  
  1         1  
  1         19  
  4         247  
215 4 50       16 croak($@) if $@;
216             }
217 1     1   7 no strict 'refs';
  1         1  
  1         65  
218 3         6 push @{"${caller}::ISA"} => @$parent;
  3         39  
219             }
220             else {
221 1     1   5 no strict 'refs';
  1         2  
  1         119  
222 1         2 push @{"${caller}::ISA"} => 'Test::Class';
  1         229  
223             }
224 4 100       59 if ( my $attributes = delete $args{attributes} ) {
225 1 50 33     6 if ( ref $attributes && 'ARRAY' ne ref $attributes ) {
226 0         0 croak(
227             "Argument to 'attributes' must be a classname or array of classnames, not ($attributes)"
228             );
229             }
230 1 50       5 $attributes = [$attributes] unless ref $attributes;
231 1         2 foreach my $attr (@$attributes) {
232 1         4 my $method = "$caller\::$attr";
233 1     1   5 no strict 'refs';
  1         1  
  1         220  
234             *$method = sub {
235 4     4   9067 my $test = shift;
236 4 100       22 return $test->{$method} unless @_;
237 3 50       11 if ( @_ > 1 ) {
238 0         0 croak("You may not pass more than one argument to '$method'");
239             }
240 3         11 $test->{$method} = shift;
241 3         10 return $test;
242 1         1346 };
243             }
244             }
245 4 100       15 if ( my $is_abstract = delete $args{is_abstract} ) {
246 2         143 $IS_ABSTRACT{$caller} = $is_abstract;
247             }
248             else {
249 2         192 $IS_ABSTRACT{$caller} = 0;
250             }
251             }
252             }
253              
254             =head1 TUTORIAL
255              
256             If you're not familiar with using L, please see my tutorial at:
257              
258             =over 4
259              
260             =item * L
261              
262             =item * L
263              
264             =item * L
265              
266             =item * L
267              
268             =item * L
269              
270             =back
271              
272              
273             =head1 AUTHOR
274              
275             Curtis "Ovid" Poe, C<< >>
276              
277             =head1 BUGS
278              
279             Please report any bugs or feature requests to C
280             rt.cpan.org>, or through the web interface at
281             L. I will be
282             notified, and then you'll automatically be notified of progress on your bug as
283             I make changes.
284              
285             =head1 SUPPORT
286              
287             You can find documentation for this module with the perldoc command.
288              
289             perldoc Test::Class::Most
290              
291             You can also look for information at:
292              
293             =over 4
294              
295             =item * RT: CPAN's request tracker
296              
297             L
298              
299             =item * AnnoCPAN: Annotated CPAN documentation
300              
301             L
302              
303             =item * CPAN Ratings
304              
305             L
306              
307             =item * Search CPAN
308              
309             L
310              
311             =back
312              
313             =head1 SEE ALSO
314              
315             =over 4
316              
317             =item * L
318              
319             xUnit-style testing in Perl
320              
321             =item * L
322              
323             The most popular CPAN test modules bundled into one module.
324              
325             =item * L
326              
327             I stole this code. Thanks C!
328              
329             =back
330              
331             =head1 ACKNOWLEDGEMENTS
332              
333             Thanks to Adrian Howard for L, Adam Kennedy for maintaining it
334             and C for L.
335              
336             =head1 COPYRIGHT & LICENSE
337              
338             Copyright 2010 Curtis "Ovid" Poe, all rights reserved.
339              
340             This program is free software; you can redistribute it and/or modify it under
341             the same terms as Perl itself.
342              
343             =cut
344              
345 1     1   6 no warnings 'void';
  1         1  
  1         40  
346             "Boilerplate is bad, m'kay";