Commit | Line | Data |
e4fc8a1e |
1 | #!/usr/bin/perl -w |
2 | |
3 | use strict; |
4 | |
5 | use Test::Harness; |
6 | use Getopt::Long; |
7 | use Pod::Usage 1.12; |
8 | use File::Spec; |
9 | |
10 | use vars qw( $VERSION ); |
11 | $VERSION = "1.04"; |
12 | |
13 | my @ext = (); |
14 | my $shuffle = 0; |
15 | my $dry = 0; |
16 | my $blib = 0; |
17 | my $recurse = 0; |
18 | my @includes = (); |
19 | my @switches = (); |
20 | |
21 | # Allow cuddling the paths with the -I |
22 | @ARGV = map { /^(-I)(.+)/ ? ($1,$2) : $_ } @ARGV; |
23 | |
24 | # Stick any default switches at the beginning, so they can be overridden |
25 | # by the command line switches. |
26 | unshift @ARGV, split( " ", $ENV{PROVE_SWITCHES} ) if defined $ENV{PROVE_SWITCHES}; |
27 | |
28 | Getopt::Long::Configure( "no_ignore_case" ); |
29 | Getopt::Long::Configure( "bundling" ); |
30 | GetOptions( |
31 | 'b|blib' => \$blib, |
32 | 'd|debug' => \$Test::Harness::debug, |
33 | 'D|dry' => \$dry, |
34 | 'h|help|?' => sub {pod2usage({-verbose => 1, -input => \*DATA}); exit}, |
35 | 'H|man' => sub {pod2usage({-verbose => 2, -input => \*DATA}); exit}, |
36 | 'I=s@' => \@includes, |
37 | 'r|recurse' => \$recurse, |
38 | 's|shuffle' => \$shuffle, |
39 | 't' => sub { unshift @switches, "-t" }, # Always want -t up front |
40 | 'T' => sub { unshift @switches, "-T" }, # Always want -T up front |
41 | 'v|verbose' => \$Test::Harness::verbose, |
42 | 'V|version' => sub { print_version(); exit; }, |
43 | 'ext=s@' => \@ext, |
44 | ) or exit 1; |
45 | |
46 | # Build up extensions regex |
47 | @ext = map { split /,/ } @ext; |
48 | s/^\.// foreach @ext; |
49 | @ext = ("t") unless @ext; |
50 | my $ext_regex = join( "|", map { quotemeta } @ext ); |
51 | $ext_regex = qr/\.($ext_regex)$/; |
52 | |
53 | # Handle blib includes |
54 | if ( $blib ) { |
55 | my @blibdirs = blibdirs(); |
56 | if ( @blibdirs ) { |
57 | unshift @includes, @blibdirs; |
58 | } else { |
59 | warn "No blib directories found.\n"; |
60 | } |
61 | } |
62 | |
63 | # Build up TH switches |
64 | push( @switches, map { /\s/ && !/^".*"$/ ? qq["-I$_"] : "-I$_" } @includes ); |
65 | $Test::Harness::Switches = join( " ", @switches ); |
66 | print "# \$Test::Harness::Switches: $Test::Harness::Switches\n" if $Test::Harness::debug; |
67 | |
68 | my @tests; |
69 | @ARGV = File::Spec->curdir unless @ARGV; |
70 | push( @tests, -d $_ ? all_in( $_ ) : $_ ) for @ARGV; |
71 | |
72 | if ( @tests ) { |
73 | shuffle(@tests) if $shuffle; |
74 | if ( $dry ) { |
75 | print join( "\n", @tests, "" ); |
76 | } else { |
77 | print "# ", scalar @tests, " tests to run\n" if $Test::Harness::debug; |
78 | runtests(@tests); |
79 | } |
80 | } |
81 | |
82 | sub all_in { |
83 | my $start = shift; |
84 | |
85 | my @hits = (); |
86 | |
87 | local *DH; |
88 | if ( opendir( DH, $start ) ) { |
89 | while ( my $file = readdir DH ) { |
90 | next if $file eq File::Spec->updir || $file eq File::Spec->curdir; |
91 | next if $file eq ".svn"; |
92 | next if $file eq "CVS"; |
93 | |
94 | my $currfile = File::Spec->catfile( $start, $file ); |
95 | if ( -d $currfile ) { |
96 | push( @hits, all_in( $currfile ) ) if $recurse; |
97 | } else { |
98 | push( @hits, $currfile ) if $currfile =~ $ext_regex; |
99 | } |
100 | } |
101 | } else { |
102 | warn "$start: $!\n"; |
103 | } |
104 | |
105 | return @hits; |
106 | } |
107 | |
108 | sub shuffle { |
109 | # Fisher-Yates shuffle |
110 | my $i = @_; |
111 | while ($i) { |
112 | my $j = rand $i--; |
113 | @_[$i, $j] = @_[$j, $i]; |
114 | } |
115 | } |
116 | |
117 | sub print_version { |
118 | printf( "prove v%s, using Test::Harness v%s and Perl v%vd\n", |
119 | $VERSION, $Test::Harness::VERSION, $^V ); |
120 | } |
121 | |
122 | # Stolen directly from blib.pm |
123 | sub blibdirs { |
124 | my $dir = File::Spec->curdir; |
125 | if ($^O eq 'VMS') { |
126 | ($dir = VMS::Filespec::unixify($dir)) =~ s-/\z--; |
127 | } |
128 | my $archdir = "arch"; |
129 | if ( $^O eq "MacOS" ) { |
130 | # Double up the MP::A so that it's not used only once. |
131 | $archdir = $MacPerl::Architecture = $MacPerl::Architecture; |
132 | } |
133 | |
134 | my $i = 5; |
135 | while ($i--) { |
136 | my $blib = File::Spec->catdir( $dir, "blib" ); |
137 | my $blib_lib = File::Spec->catdir( $blib, "lib" ); |
138 | my $blib_arch = File::Spec->catdir( $blib, $archdir ); |
139 | |
140 | if ( -d $blib && -d $blib_arch && -d $blib_lib ) { |
141 | return ($blib_arch,$blib_lib); |
142 | } |
143 | $dir = File::Spec->catdir($dir, File::Spec->updir); |
144 | } |
145 | warn "$0: Cannot find blib\n"; |
146 | return; |
147 | } |
148 | |
149 | __END__ |
150 | |
151 | =head1 NAME |
152 | |
153 | prove -- A command-line tool for running tests against Test::Harness |
154 | |
155 | =head1 SYNOPSIS |
156 | |
157 | prove [options] [files/directories] |
158 | |
159 | Options: |
160 | |
161 | -b, --blib Adds blib/lib to the path for your tests, a la "use blib". |
162 | -d, --debug Includes extra debugging information. |
163 | -D, --dry Dry run: Show the tests to run, but don't run them. |
164 | --ext=x Extensions (defaults to .t) |
165 | -h, --help Display this help |
166 | -H, --man Longer manpage for prove |
167 | -I Add libraries to @INC, as Perl's -I |
168 | -r, --recurse Recursively descend into directories. |
169 | -s, --shuffle Run the tests in a random order. |
170 | -T Enable tainting checks |
171 | -t Enable tainting warnings |
172 | -v, --verbose Display standard output of test scripts while running them. |
173 | -V, --version Display version info |
174 | |
175 | Single-character options may be stacked. Default options may be set by |
176 | specifying the PROVE_SWITCHES environment variable. |
177 | |
178 | =head1 OVERVIEW |
179 | |
180 | F<prove> is a command-line interface to the test-running functionality |
181 | of C<Test::Harness>. With no arguments, it will run all tests in the |
182 | current directory. |
183 | |
184 | Shell metacharacters may be used with command lines options and will be exanded |
185 | via C<glob>. |
186 | |
187 | =head1 PROVE VS. "MAKE TEST" |
188 | |
189 | F<prove> has a number of advantages over C<make test> when doing development. |
190 | |
191 | =over 4 |
192 | |
193 | =item * F<prove> is designed as a development tool |
194 | |
195 | Perl users typically run the test harness through a makefile via |
196 | C<make test>. That's fine for module distributions, but it's |
197 | suboptimal for a test/code/debug development cycle. |
198 | |
199 | =item * F<prove> is granular |
200 | |
201 | F<prove> lets your run against only the files you want to check. |
202 | Running C<prove t/live/ t/master.t> checks every F<*.t> in F<t/live>, |
203 | plus F<t/master.t>. |
204 | |
205 | =item * F<prove> has an easy verbose mode |
206 | |
207 | F<prove> has a C<-v> option to see the raw output from the tests. |
208 | To do this with C<make test>, you must set C<HARNESS_VERBOSE=1> in |
209 | the environment. |
210 | |
211 | =item * F<prove> can run under taint mode |
212 | |
213 | F<prove>'s C<-T> runs your tests under C<perl -T>, and C<-t> runs them |
214 | under C<perl -t>. |
215 | |
216 | =item * F<prove> can shuffle tests |
217 | |
218 | You can use F<prove>'s C<--shuffle> option to try to excite problems |
219 | that don't show up when tests are run in the same order every time. |
220 | |
221 | =item * F<prove> doesn't rely on a make tool |
222 | |
223 | Not everyone wants to write a makefile, or use L<ExtUtils::MakeMaker> |
224 | to do so. F<prove> has no external dependencies. |
225 | |
226 | =item * Not everything is a module |
227 | |
228 | More and more users are using Perl's testing tools outside the |
229 | context of a module distribution, and may not even use a makefile |
230 | at all. |
231 | |
232 | =back |
233 | |
234 | =head1 COMMAND LINE OPTIONS |
235 | |
236 | =head2 -b, --blib |
237 | |
238 | Adds blib/lib to the path for your tests, a la "use blib". |
239 | |
240 | =head2 -d, --debug |
241 | |
242 | Include debug information about how F<prove> is being run. This |
243 | option doesn't show the output from the test scripts. That's handled |
244 | by -v,--verbose. |
245 | |
246 | =head2 -D, --dry |
247 | |
248 | Dry run: Show the tests to run, but don't run them. |
249 | |
250 | =head2 --ext=extension |
251 | |
252 | Specify extensions of the test files to run. By default, these are .t, |
253 | but you may have other non-.t test files, most likely .sh shell scripts. |
254 | The --ext is repeatable. |
255 | |
256 | =head2 -I |
257 | |
258 | Add libraries to @INC, as Perl's -I |
259 | |
260 | =head2 -r, --recurse |
261 | |
262 | Descends into subdirectories of any directories specified, looking for tests. |
263 | |
264 | =head2 -s, --shuffle |
265 | |
266 | Sometimes tests are accidentally dependent on tests that have been |
267 | run before. This switch will shuffle the tests to be run prior to |
268 | running them, thus ensuring that hidden dependencies in the test |
269 | order are likely to be revealed. The author hopes the run the |
270 | algorithm on the preceding sentence to see if he can produce something |
271 | slightly less awkward. |
272 | |
273 | =head2 -t |
274 | |
275 | Runs test programs under perl's -t taint warning mode. |
276 | |
277 | =head2 -T |
278 | |
279 | Runs test programs under perl's -T taint mode. |
280 | |
281 | =head2 -v, --verbose |
282 | |
283 | Display standard output of test scripts while running them. |
284 | |
285 | =head2 -V, --version |
286 | |
287 | Display version info. |
288 | |
289 | =head1 BUGS |
290 | |
291 | Please use the CPAN bug ticketing system at L<http://rt.cpan.org/>. |
292 | You can also mail bugs, fixes and enhancements to |
293 | C<< <bug-test-harness@rt.cpan.org> >>. |
294 | |
295 | =head1 TODO |
296 | |
297 | =over 4 |
298 | |
299 | =item * |
300 | |
301 | Shuffled tests must be recreatable |
302 | |
303 | =item * |
304 | |
305 | Add a flag to run prove under Devel::Cover |
306 | |
307 | =back |
308 | |
309 | =head1 AUTHORS |
310 | |
311 | Andy Lester C<< <andy@petdance.com> >> |
312 | |
313 | =head1 COPYRIGHT |
314 | |
315 | Copyright 2003 by Andy Lester C<< <andy@petdance.com> >>. |
316 | |
317 | This program is free software; you can redistribute it and/or |
318 | modify it under the same terms as Perl itself. |
319 | |
320 | See L<http://www.perl.com/perl/misc/Artistic.html>. |
321 | |
322 | =cut |