File Coverage

blib/lib/Test/Class/Moose/Load.pm
Criterion Covered Total %
statement 66 66 100.0
branch 9 10 90.0
condition n/a
subroutine 22 22 100.0
pod 1 1 100.0
total 98 99 98.9


line stmt bran cond sub pod time code
1             package Test::Class::Moose::Load;
2              
3             # ABSTRACT: Load L<Test::Class::Moose> classes automatically.
4              
5 44     44   5366121 use strict;
  44         4822  
  44         915  
6 43     43   4350 use warnings;
  43         19920  
  43         848  
7 42     42   13613 use namespace::autoclean;
  42         322677  
  42         330  
8              
9             our $VERSION = '0.97';
10              
11 40     40   5370 use File::Find;
  40         7527  
  40         1660  
12 40     40   3337 use File::Spec;
  40         18714  
  40         13437  
13              
14             # Override to get your own filter
15             sub is_test_class {
16 384     384 1 4351 my ( undef, $file, undef ) = @_;
17              
18             # By default, we only care about .pm files
19 384 100       21321 if ( $file =~ /\.pm$/ ) {
20 195         666 return 1;
21             }
22 201         21812 return;
23             }
24              
25             my %Added_to_INC;
26              
27             sub _load {
28 195     195   25324 my ( $class, $file, $dir ) = @_;
29              
30 195         786 $file =~ s{\.pm$}{}; # remove .pm extension
31 184         395 $file =~ s{\\}{/}g; # to make win32 happy
32 184         297 $dir =~ s{\\}{/}g; # to make win32 happy
33 184         1584 $file =~ s/^$dir//;
34 184         1937 my $_package = join '::' => grep $_ => File::Spec->splitdir($file);
35              
36             # untaint that puppy!
37 184         968 my ($package) = $_package =~ /^([[:word:]]+(?:::[[:word:]]+)*)$/;
38              
39             # Filter out bad classes (mainly this means things in .svn and similar)
40 184 50       489 return unless defined $package;
41              
42 184 100       646 unshift @INC => $dir unless $Added_to_INC{$dir}++;
43              
44             {
45 184         310 local $SIG{__DIE__} = sub {
46 17     17   111317 undef $SIG{__DIE__};
47 17         116 require Carp;
48 17         60 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
49 17         3300 Carp::confess(@_);
50 184         1086 };
51              
52             # either "require" it or "use" it with no import list. Otherwise, this
53             # module will inherit from Test::Class::Moose and break everything.
54 40     40   11795 eval "use $package ()"; ## no critic
  39     37   268037  
  39     1   750  
  37     1   12867  
  37     1   66396  
  37     1   565  
  184     1   9881  
  1     1   3  
  1     1   16  
  1     1   6  
  1     1   2  
  1     1   12  
  1         6  
  1         2  
  1         12  
  1         8  
  1         3  
  1         18  
  1         6  
  1         2  
  1         13  
  1         6  
  1         1  
  1         11  
55             }
56 184 100       8210 die $@ if $@;
57             }
58              
59             sub import {
60 37     37   242 my ( $class, @directories ) = @_;
61              
62 37         105 foreach my $dir (@directories) {
63 81         973 $dir = File::Spec->catdir( split '/', $dir );
64             find(
65             { no_chdir => 1,
66             wanted => sub {
67 373     373   1194 my @args = ( $File::Find::name, $dir );
68 373 100       1531 if ( $class->is_test_class(@args) ) {
69 184         420 $class->_load(@args);
70             }
71             },
72             },
73 81         8926 $dir
74             );
75             }
76             }
77              
78             1;
79              
80             __END__
81              
82             =pod
83              
84             =encoding UTF-8
85              
86             =head1 NAME
87              
88             Test::Class::Moose::Load - Load L<Test::Class::Moose> classes automatically.
89              
90             =head1 VERSION
91              
92             version 0.97
93              
94             =head1 SYNOPSIS
95              
96             use Test::Class::Moose::Load qw(t/tests t/lib);
97             Test::Class::Moose->runtests;
98              
99             =head1 DESCRIPTION
100              
101             Note: This helper module was blatantly stolen from L<Test::Class::Load>.
102             However, since your author is the person who originally wrote that code, he
103             doesn't feel too bad.
104              
105             Without a loader, you would have to manually load each test class in your test
106             file. This would look something like this:
107              
108             #!/usr/bin/perl -T
109              
110             use strict;
111             use warnings;
112              
113             use Test::Class::Moose::Runner;
114              
115             use lib 't/tests';
116              
117             use MyTest::Foo;
118             use MyTest::Foo::Bar;
119             use MyTest::Foo::Baz;
120              
121             Test::Class::Moose::Runner->runtests;
122              
123             This causes a problem, though. When you're writing a test class, it's easy to
124             forget to add it to the helper script. Then you run your huge test suite and
125             see that all tests pass, even though you don't notice that it didn't run your
126             new test class. Or you delete a test class and you forget to remove it from
127             the helper script.
128              
129             L<Test::Class::Moose::Load> automatically finds and loads your test classes
130             for you. There is no longer a need to list them individually.
131              
132             =head1 EXPORT
133              
134             None.
135              
136             =head1 BASIC USAGE
137              
138             Using L<Test::Class::Moose::Load> is as simple as this:
139              
140             #!/usr/bin/perl -T
141              
142             use strict;
143             use warnings;
144              
145             use Test::Class::Moose::Runner;
146             use Test::Class::Moose::Load 't/tests';
147              
148             Test::Class::Moose::Runner->new(\%args)->runtests;
149              
150             That will search through all files in the C<t/tests> directory and
151             automatically load anything which ends in C<.pm>. You should only put test
152             classes in those directories.
153              
154             If you have test classes in more than one directory, that's OK. Just list all
155             of them in the import list.
156              
157             use Test::Class::Moose::Load qw<
158             t/customer
159             t/order
160             t/inventory
161             >;
162             Test::Class::Moose::Runner->runtests;
163              
164             =head1 ADVANCED USAGE
165              
166             Here's some examples of advanced usage of L<Test::Class::Moose::Load>.
167              
168             =head2 FILTER LOADED CLASSES
169              
170             You can redefine the filtering criteria, that is, decide what classes are
171             picked up and what others are not. You do this simply by subclassing
172             L<Test::Class::Moose::Load> overriding the C<is_test_class()> method. You
173             might want to do this to only load modules which inherit from
174             L<Test::Class::Moose>, or anything else for that matter.
175              
176             =over 4
177              
178             =item B<is_test_class>
179              
180             $is_test_class = $class->is_test_class( $file, $directory )
181              
182             Returns true if C<$file> in C<$directory> should be considered a test class
183             and be loaded by L<Test::Class::Moose::Load>. The default filter simply
184             returns true if C<$file> ends with C<.pm>
185              
186             =back
187              
188             For example:
189              
190             use strict;
191             use warnings;
192              
193             package My::Loader;
194             use base qw( Test::Class::Moose::Load );
195              
196             # Overriding this selects what test classes
197             # are considered by T::C::Load
198             sub is_test_class {
199             my ( $class, $file, $dir ) = @_;
200              
201             # return unless it's a .pm (the default)
202             return unless $class->SUPER::is_test_class( $file, $dir );
203              
204             # and only allow .pm files with "Good" in their filename
205             return $file =~ m{Good};
206             }
207              
208             1;
209              
210             =head2 CUSTOMIZING TEST RUNS
211              
212             One problem with this style of testing is that you run I<all> of the tests
213             every time you need to test something. If you want to run only one test
214             class, it's problematic. The easy way to do this is to change your helper
215             script by deleting the C<runtests> call:
216              
217             #!/usr/bin/perl -T
218              
219             use strict;
220             use warnings;
221              
222             use Test::Class::Moose::Load 't/tests';
223              
224             Then, just make sure that all of your test classes inherit from your own base
225             class which runs the tests for you. It might looks something like this:
226              
227             package My::Test::Class::Moose;
228              
229             use strict;
230             use warnings;
231              
232             use Test::Class::Moose::Runner;
233              
234             use base 'Test::Class::Moose';
235              
236             INIT { Test::Class::Moose::Runner->new->runtests } # here's the magic!
237              
238             1;
239              
240             Then you can run an individual test class by using the C<prove> utility, tell
241             it the directory of the test classes and the name of the test package you wish
242             to run:
243              
244             prove -lv -It/tests Some::Test::Class::Moose
245              
246             You can even automate this by binding it to a key in C<vim>:
247              
248             noremap ,t :!prove -lv -It/tests %<CR>
249              
250             Then you can just type C<,t> ('comma', 'tee') and it will run the tests for
251             your test class or the tests for your test script (if you're using a
252             traditional L<Test::More> style script).
253              
254             Of course, you can still run your helper script with C<prove>, C<make test> or
255             C<./Build test> to run all of your test classes.
256              
257             If you do that, you'll have to make sure that the C<-I> switches point to your
258             test class directories.
259              
260             =head1 SECURITY
261              
262             L<Test::Class::Moose::Load> is taint safe. Because we're reading the class
263             names from the directory structure, they're marked as tainted when running
264             under taint mode. We use the following ultra-paranoid bit of code to untaint
265             them. Please file a bug report if this is too restrictive.
266              
267             my ($package) = $_package =~ /^([[:word:]]+(?:::[[:word:]]+)*)$/;
268              
269             =head1 ACKNOWLEDGMENTS
270              
271             Thanks to David Wheeler for the idea and Adrian Howard for
272             L<Test::Class::Moose>.
273              
274             =head1 BUGS
275              
276             Please report any bugs or feature requests to
277             C<bug-test-class-load@rt.cpan.org>, or through the web interface at
278             L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-Class-Load>. I will be
279             notified, and then you'll automatically be notified of progress on your bug as
280             I make changes.
281              
282             Bugs may be submitted at L<https://github.com/houseabsolute/test-class-moose/issues>.
283              
284             I am also usually active on IRC as 'autarch' on C<irc://irc.perl.org>.
285              
286             =head1 SOURCE
287              
288             The source code repository for Test-Class-Moose can be found at L<https://github.com/houseabsolute/test-class-moose>.
289              
290             =head1 AUTHORS
291              
292             =over 4
293              
294             =item *
295              
296             Curtis "Ovid" Poe <ovid@cpan.org>
297              
298             =item *
299              
300             Dave Rolsky <autarch@urth.org>
301              
302             =back
303              
304             =head1 COPYRIGHT AND LICENSE
305              
306             This software is copyright (c) 2012 - 2019 by Curtis "Ovid" Poe.
307              
308             This is free software; you can redistribute it and/or modify it under
309             the same terms as the Perl 5 programming language system itself.
310              
311             The full text of the license can be found in the
312             F<LICENSE> file included with this distribution.
313              
314             =cut