10 use vars qw($VERSION);
14 App::Prove - Implements the C<prove> command.
26 L<Test::Harness> provides a command, C<prove>, which runs a TAP based
27 test suite and prints a report. The C<prove> command is a minimal
28 wrapper around an instance of this module.
34 my $app = App::Prove->new;
35 $app->process_args(@ARGV);
40 use constant IS_WIN32 => ( $^O =~ /^(MS)?Win32$/ );
41 use constant IS_VMS => $^O eq 'VMS';
42 use constant IS_UNIXY => !( IS_VMS || IS_WIN32 );
44 use constant STATE_FILE => IS_UNIXY ? '.prove' : '_prove';
45 use constant RC_FILE => IS_UNIXY ? '.proverc' : '_proverc';
47 use constant PLUGINS => 'App::Prove::Plugin';
53 archive argv blib color directives exec failures fork formatter
54 harness includes modules plugins jobs lib merge parse quiet
55 really_quiet recurse backwards shuffle taint_fail taint_warn timer
56 verbose warnings_fail warnings_warn show_help show_man
57 show_version test_args state dry
59 for my $attr (@ATTR) {
63 croak "$attr is read-only" if @_;
75 Create a new C<App::Prove>. Optionally a hash ref of attribute
76 initializers may be passed.
82 my $args = shift || {};
91 harness_class => 'TAP::Harness',
92 _state => App::Prove::State->new( { store => STATE_FILE } ),
95 for my $attr (@ATTR) {
96 if ( exists $args->{$attr} ) {
98 # TODO: Some validation here
99 $self->{$attr} = $args->{$attr};
105 =head3 C<add_rc_file>
107 $prove->add_rc_file('myproj/.proverc');
109 Called before C<process_args> to prepend the contents of an rc file to
115 my ( $self, $rc_file ) = @_;
118 open RC, "<$rc_file" or croak "Can't read $rc_file ($!)";
119 while ( defined( my $line = <RC> ) ) {
120 push @{ $self->{rc_opts} }, grep $_ && $_ !~ /^#/,
121 $line =~ m{ ' ([^']*) ' | " ([^"]*) " | (\#.*) | (\S*) }xg;
126 =head3 C<process_args>
128 $prove->process_args(@args);
130 Processes the command-line arguments. Attributes will be set
131 appropriately. Any filenames may be found in the C<argv> attribute.
133 Dies on invalid arguments.
141 unshift @rc, glob '~/' . RC_FILE if IS_UNIXY;
143 # Preprocess meta-args.
145 while ( defined( my $arg = shift ) ) {
146 if ( $arg eq '--norc' ) {
149 elsif ( $arg eq '--rc' ) {
150 defined( my $rc = shift )
151 or croak "Missing argument to --rc";
154 elsif ( $arg =~ m{^--rc=(.+)$} ) {
162 # Everything after the arisdottle '::' gets passed as args to
164 if ( defined( my $stop_at = _first_pos( '::', @args ) ) ) {
165 my @test_args = splice @args, $stop_at;
167 $self->{test_args} = \@test_args;
170 # Grab options from RC files
171 $self->add_rc_file($_) for grep -f, @rc;
172 unshift @args, @{ $self->{rc_opts} };
174 if ( my @bad = map {"-$_"} grep {/^-(man|help)$/} @args ) {
175 die "Long options should be written with two dashes: ",
176 join( ', ', @bad ), "\n";
183 Getopt::Long::Configure( 'no_ignore_case', 'bundling' );
185 # Don't add coderefs to GetOptions
187 'v|verbose' => \$self->{verbose},
188 'f|failures' => \$self->{failures},
189 'l|lib' => \$self->{lib},
190 'b|blib' => \$self->{blib},
191 's|shuffle' => \$self->{shuffle},
192 'color!' => \$self->{color},
193 'colour!' => \$self->{color},
194 'c' => \$self->{color},
195 'D|dry' => \$self->{dry},
196 'harness=s' => \$self->{harness},
197 'formatter=s' => \$self->{formatter},
198 'r|recurse' => \$self->{recurse},
199 'reverse' => \$self->{backwards},
200 'fork' => \$self->{fork},
201 'p|parse' => \$self->{parse},
202 'q|quiet' => \$self->{quiet},
203 'Q|QUIET' => \$self->{really_quiet},
204 'e|exec=s' => \$self->{exec},
205 'm|merge' => \$self->{merge},
206 'I=s@' => $self->{includes},
207 'M=s@' => $self->{modules},
208 'P=s@' => $self->{plugins},
209 'state=s@' => $self->{state},
210 'directives' => \$self->{directives},
211 'h|help|?' => \$self->{show_help},
212 'H|man' => \$self->{show_man},
213 'V|version' => \$self->{show_version},
214 'a|archive=s' => \$self->{archive},
215 'j|jobs=i' => \$self->{jobs},
216 'timer' => \$self->{timer},
217 'T' => \$self->{taint_fail},
218 't' => \$self->{taint_warn},
219 'W' => \$self->{warnings_fail},
220 'w' => \$self->{warnings_warn},
221 ) or croak('Unable to continue');
223 # Stash the remainder of argv for later
224 $self->{argv} = [@ARGV];
233 return $_ if $_[$_] eq $want;
238 sub _exit { exit( $_[1] || 0 ) }
241 my ( $self, $verbosity ) = @_;
243 eval('use Pod::Usage 1.12 ()');
244 if ( my $err = $@ ) {
245 die 'Please install Pod::Usage for the --help option '
246 . '(or try `perldoc prove`.)'
250 Pod::Usage::pod2usage( { -verbose => $verbosity } );
258 return -t STDOUT && !IS_WIN32;
266 if ( defined $self->color ? $self->color : $self->_color_default ) {
270 if ( $self->archive ) {
271 $self->require_harness( archive => 'TAP::Harness::Archive' );
272 $args{archive} = $self->archive;
275 if ( my $jobs = $self->jobs ) {
279 if ( my $fork = $self->fork ) {
283 if ( my $harness_opt = $self->harness ) {
284 $self->require_harness( harness => $harness_opt );
287 if ( my $formatter = $self->formatter ) {
288 $args{formatter_class} = $formatter;
291 if ( $self->taint_fail && $self->taint_warn ) {
292 die '-t and -T are mutually exclusive';
295 if ( $self->warnings_fail && $self->warnings_warn ) {
296 die '-w and -W are mutually exclusive';
299 for my $a (qw( lib switches )) {
300 my $method = "_get_$a";
301 my $val = $self->$method();
302 $args{$a} = $val if defined $val;
305 # Handle verbose, quiet, really_quiet flags
306 my %verb_map = ( verbose => 1, quiet => -1, really_quiet => -2, );
308 my @verb_adj = grep {$_} map { $self->$_() ? $verb_map{$_} : 0 }
311 die "Only one of verbose, quiet or really_quiet should be specified\n"
314 $args{verbosity} = shift @verb_adj || 0;
316 for my $a (qw( merge failures timer directives )) {
317 $args{$a} = 1 if $self->$a();
320 $args{errors} = 1 if $self->parse;
322 # defined but zero-length exec runs test files as binaries
323 $args{exec} = [ split( /\s+/, $self->exec ) ]
324 if ( defined( $self->exec ) );
326 if ( defined( my $test_args = $self->test_args ) ) {
327 $args{test_args} = $test_args;
330 return ( \%args, $self->{harness_class} );
334 my ( $self, $class, @search ) = @_;
336 croak "Bad module name $class"
337 unless $class =~ /^ \w+ (?: :: \w+ ) *$/x;
339 for my $pfx (@search) {
340 my $name = join( '::', $pfx, $class );
342 eval "require $name";
343 return $name unless $@;
346 eval "require $class";
347 return $class unless $@;
351 sub _load_extension {
352 my ( $self, $class, @search ) = @_;
355 if ( $class =~ /^(.*?)=(.*)/ ) {
357 @args = split( /,/, $2 );
360 if ( my $name = $self->_find_module( $class, @search ) ) {
361 $name->import(@args);
364 croak "Can't load module $class";
368 sub _load_extensions {
369 my ( $self, $ext, @search ) = @_;
370 $self->_load_extension( $_, @search ) for @$ext;
375 Perform whatever actions the command line args specified. The C<prove>
376 command line tool consists of the following code:
380 my $app = App::Prove->new;
381 $app->process_args(@ARGV);
389 if ( $self->show_help ) {
392 elsif ( $self->show_man ) {
395 elsif ( $self->show_version ) {
396 $self->print_version;
398 elsif ( $self->dry ) {
399 print "$_\n" for $self->_get_tests;
403 $self->_load_extensions( $self->modules );
404 $self->_load_extensions( $self->plugins, PLUGINS );
406 local $ENV{TEST_VERBOSE} = 1 if $self->verbose;
408 $self->_runtests( $self->_get_args, $self->_get_tests );
417 my $state = $self->{_state};
418 if ( defined( my $state_switch = $self->state ) ) {
419 $state->apply_switch(@$state_switch);
422 my @tests = $state->get_tests( $self->recurse, @{ $self->argv } );
424 $self->_shuffle(@tests) if $self->shuffle;
425 @tests = reverse @tests if $self->backwards;
431 my ( $self, $args, $harness_class, @tests ) = @_;
432 my $harness = $harness_class->new($args);
436 $self->{_state}->observe_test(@_);
440 my $aggregator = $harness->runtests(@tests);
442 $self->_exit( $aggregator->has_problems ? 1 : 0 );
451 # notes that -T or -t must be at the front of the switches!
452 if ( $self->taint_fail ) {
453 push @switches, '-T';
455 elsif ( $self->taint_warn ) {
456 push @switches, '-t';
458 if ( $self->warnings_fail ) {
459 push @switches, '-W';
461 elsif ( $self->warnings_warn ) {
462 push @switches, '-w';
465 if ( defined( my $hps = $ENV{HARNESS_PERL_SWITCHES} ) ) {
466 push @switches, $hps;
469 return @switches ? \@switches : ();
479 push @libs, 'blib/lib', 'blib/arch';
481 if ( @{ $self->includes } ) {
482 push @libs, @{ $self->includes };
486 @libs = map { File::Spec->rel2abs($_) } @libs;
489 return @libs ? \@libs : ();
495 # Fisher-Yates shuffle
499 @_[ $i, $j ] = @_[ $j, $i ];
504 =head3 C<require_harness>
506 Load a harness replacement class.
508 $prove->require_harness($for => $class_name);
512 sub require_harness {
513 my ( $self, $for, $class ) = @_;
515 eval("require $class");
516 die "$class is required to use the --$for feature: $@" if $@;
518 $self->{harness_class} = $class;
523 =head3 C<print_version>
525 Display the version numbers of the loaded L<TAP::Harness> and the
533 "TAP::Harness v%s and Perl v%vd\n",
534 $TAP::Harness::VERSION, $^V
542 # vim:ts=4:sw=4:et:sta
548 After command line parsing the following attributes reflect the values
549 of the corresponding command line switches. They may be altered before
594 =item C<really_quiet>
602 =item C<show_version>
618 =item C<warnings_fail>
620 =item C<warnings_warn>