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