17 @ISA = qw( App::Prove );
21 my $self = $class->SUPER::new(@_);
26 sub _color_default {0}
30 push @{ $self->{_log} }, [ '_runtests', @_ ];
35 my @log = @{ $self->{_log} };
49 return [ map { File::Spec->rel2abs($_) } @$ar ];
54 sub test_log_import { push @import_log, [@_] }
57 my @log = @import_log;
62 my @plugin_load_log = ();
63 sub test_log_plugin_load { push @plugin_load_log, [@_] }
65 sub get_plugin_load_log {
66 my @log = @plugin_load_log;
67 @plugin_load_log = ();
72 my ( @ATTR, %DEFAULT_ASSERTION, @SCHEDULE );
74 # see the "ACTUAL TEST" section at the bottom
80 archive argv blib color directives exec extension failures
81 formatter harness includes lib merge parse quiet really_quiet
82 recurse backwards shuffle taint_fail taint_warn verbose
83 warnings_fail warnings_warn
86 # what we expect if the 'expect' hash does not define it
87 %DEFAULT_ASSERTION = map { $_ => undef } @ATTR;
89 $DEFAULT_ASSERTION{includes} = $DEFAULT_ASSERTION{argv}
90 = sub { 'ARRAY' eq ref shift };
92 my @dummy_tests = map { File::Spec->catdir( 't', 'sample-tests', $_ ) }
93 qw(simple simple_yaml);
94 my $dummy_test = $dummy_tests[0];
96 ########################################################################
97 # declarations - this drives all of the subtests.
98 # The cheatsheet follows.
99 # required: name, expect
101 # args - arguments to constructor
102 # switches - command-line switches
103 # runlog - expected results of internal calls to _runtests, must
104 # match FakeProve's _log attr
105 # run_error - depends on 'runlog' (if missing, asserts no error)
106 # extra - follow-up check to handle exceptional cleanup / verification
107 # class - The App::Prove subclass to test. Defaults to FakeProve
109 { name => 'Create empty',
112 { name => 'Set all options via constructor',
115 argv => [qw(one two three)],
123 includes => [qw(four five six)],
140 argv => [qw(one two three)],
148 includes => [qw(four five six)],
164 { name => 'Call with defaults',
165 args => { argv => [qw( one two three )] },
173 'one', 'two', 'three'
178 # Test all options individually
180 # { name => 'Just archive',
182 # argv => [qw( one two three )],
197 { name => 'Just argv',
199 argv => [qw( one two three )],
202 argv => [qw( one two three )],
206 { verbosity => 0, show_count => 1 },
213 { name => 'Just blib',
215 argv => [qw( one two three )],
223 { lib => mabs( [ 'blib/lib', 'blib/arch' ] ),
228 'one', 'two', 'three'
233 { name => 'Just color',
235 argv => [qw( one two three )],
248 'one', 'two', 'three'
253 { name => 'Just directives',
255 argv => [qw( one two three )],
268 'one', 'two', 'three'
272 { name => 'Just exec',
274 argv => [qw( one two three )],
287 'one', 'two', 'three'
291 { name => 'Just failures',
293 argv => [qw( one two three )],
306 'one', 'two', 'three'
311 { name => 'Just formatter',
313 argv => [qw( one two three )],
314 formatter => 'TAP::Harness',
317 formatter => 'TAP::Harness',
321 { formatter_class => 'TAP::Harness',
326 'one', 'two', 'three'
331 { name => 'Just includes',
333 argv => [qw( one two three )],
334 includes => [qw( four five six )],
337 includes => [qw( four five six )],
341 { lib => mabs( [qw( four five six )] ),
346 'one', 'two', 'three'
350 { name => 'Just lib',
352 argv => [qw( one two three )],
360 { lib => mabs( ['lib'] ),
365 'one', 'two', 'three'
369 { name => 'Just merge',
371 argv => [qw( one two three )],
384 'one', 'two', 'three'
388 { name => 'Just parse',
390 argv => [qw( one two three )],
403 'one', 'two', 'three'
407 { name => 'Just quiet',
409 argv => [qw( one two three )],
421 'one', 'two', 'three'
425 { name => 'Just really_quiet',
427 argv => [qw( one two three )],
439 'one', 'two', 'three'
443 { name => 'Just recurse',
445 argv => [qw( one two three )],
457 'one', 'two', 'three'
461 { name => 'Just reverse',
463 argv => [qw( one two three )],
475 'three', 'two', 'one'
480 { name => 'Just shuffle',
482 argv => [qw( one two three )],
499 { name => 'Just taint_fail',
501 argv => [qw( one two three )],
509 { switches => ['-T'],
514 'one', 'two', 'three'
518 { name => 'Just taint_warn',
520 argv => [qw( one two three )],
528 { switches => ['-t'],
533 'one', 'two', 'three'
537 { name => 'Just verbose',
539 argv => [qw( one two three )],
551 'one', 'two', 'three'
555 { name => 'Just warnings_fail',
557 argv => [qw( one two three )],
565 { switches => ['-W'],
570 'one', 'two', 'three'
574 { name => 'Just warnings_warn',
576 argv => [qw( one two three )],
584 { switches => ['-w'],
589 'one', 'two', 'three'
594 # Command line parsing
595 { name => 'Switch -v',
597 argv => [qw( one two three )],
599 switches => [ '-v', $dummy_test ],
614 { name => 'Switch --verbose',
616 argv => [qw( one two three )],
618 switches => [ '--verbose', $dummy_test ],
633 { name => 'Switch -f',
635 argv => [qw( one two three )],
637 switches => [ '-f', $dummy_test ],
638 expect => { failures => 1 },
651 { name => 'Switch --failures',
653 argv => [qw( one two three )],
655 switches => [ '--failures', $dummy_test ],
656 expect => { failures => 1 },
669 { name => 'Switch -l',
671 argv => [qw( one two three )],
673 switches => [ '-l', $dummy_test ],
674 expect => { lib => 1 },
677 { lib => mabs( ['lib'] ),
687 { name => 'Switch --lib',
689 argv => [qw( one two three )],
691 switches => [ '--lib', $dummy_test ],
692 expect => { lib => 1 },
695 { lib => mabs( ['lib'] ),
705 { name => 'Switch -b',
707 argv => [qw( one two three )],
709 switches => [ '-b', $dummy_test ],
710 expect => { blib => 1 },
713 { lib => mabs( [ 'blib/lib', 'blib/arch' ] ),
723 { name => 'Switch --blib',
725 argv => [qw( one two three )],
727 switches => [ '--blib', $dummy_test ],
728 expect => { blib => 1 },
731 { lib => mabs( [ 'blib/lib', 'blib/arch' ] ),
741 { name => 'Switch -s',
743 argv => [qw( one two three )],
745 switches => [ '-s', $dummy_test ],
746 expect => { shuffle => 1 },
758 { name => 'Switch --shuffle',
760 argv => [qw( one two three )],
762 switches => [ '--shuffle', $dummy_test ],
763 expect => { shuffle => 1 },
775 { name => 'Switch -c',
777 argv => [qw( one two three )],
779 switches => [ '-c', $dummy_test ],
780 expect => { color => 1 },
793 { name => 'Switch -r',
795 argv => [qw( one two three )],
797 switches => [ '-r', $dummy_test ],
798 expect => { recurse => 1 },
810 { name => 'Switch --recurse',
812 argv => [qw( one two three )],
814 switches => [ '--recurse', $dummy_test ],
815 expect => { recurse => 1 },
827 { name => 'Switch --reverse',
829 argv => [qw( one two three )],
831 switches => [ '--reverse', @dummy_tests ],
832 expect => { backwards => 1 },
844 { name => 'Switch -p',
846 argv => [qw( one two three )],
848 switches => [ '-p', $dummy_test ],
864 { name => 'Switch --parse',
866 argv => [qw( one two three )],
868 switches => [ '--parse', $dummy_test ],
884 { name => 'Switch -q',
886 argv => [qw( one two three )],
888 switches => [ '-q', $dummy_test ],
889 expect => { quiet => 1 },
901 { name => 'Switch --quiet',
903 argv => [qw( one two three )],
905 switches => [ '--quiet', $dummy_test ],
906 expect => { quiet => 1 },
918 { name => 'Switch -Q',
920 argv => [qw( one two three )],
922 switches => [ '-Q', $dummy_test ],
923 expect => { really_quiet => 1 },
935 { name => 'Switch --QUIET',
937 argv => [qw( one two three )],
939 switches => [ '--QUIET', $dummy_test ],
940 expect => { really_quiet => 1 },
952 { name => 'Switch -m',
954 argv => [qw( one two three )],
956 switches => [ '-m', $dummy_test ],
957 expect => { merge => 1 },
970 { name => 'Switch --merge',
972 argv => [qw( one two three )],
974 switches => [ '--merge', $dummy_test ],
975 expect => { merge => 1 },
988 { name => 'Switch --directives',
990 argv => [qw( one two three )],
992 switches => [ '--directives', $dummy_test ],
993 expect => { directives => 1 },
1007 { name => 'Empty exec in .proverc',
1009 argv => [qw( one two three )],
1011 proverc => 't/proverc/emptyexec',
1012 switches => [$dummy_test],
1013 expect => { exec => '' },
1026 # Executing one word (why would it be a -s though?)
1027 { name => 'Switch --exec -s',
1029 argv => [qw( one two three )],
1031 switches => [ '--exec', '-s', $dummy_test ],
1032 expect => { exec => '-s' },
1046 { name => 'Switch --exec "/foo/bar/perl -Ilib"',
1048 argv => [qw( one two three )],
1050 switches => [ '--exec', '/foo/bar/perl -Ilib', $dummy_test ],
1051 expect => { exec => '/foo/bar/perl -Ilib' },
1054 { exec => [qw(/foo/bar/perl -Ilib)],
1064 # null exec (run tests as compiled binaries)
1065 { name => 'Switch --exec ""',
1066 switches => [ '--exec', '', $dummy_test ],
1068 exec => # ick, must workaround the || default bit with a sub
1069 sub { my $val = shift; defined($val) and !length($val) }
1084 { name => 'Load plugin',
1085 switches => [ '-P', 'Dummy', $dummy_test ],
1087 argv => [qw( one two three )],
1090 plugins => ['Dummy'],
1093 my @loaded = get_import_log();
1094 is_deeply \@loaded, [ ['App::Prove::Plugin::Dummy'] ],
1109 { name => 'Load plugin (args)',
1110 switches => [ '-P', 'Dummy=cracking,cheese,gromit', $dummy_test ],
1112 argv => [qw( one two three )],
1115 plugins => ['Dummy'],
1118 my @loaded = get_import_log();
1120 [ [ 'App::Prove::Plugin::Dummy', 'cracking', 'cheese',
1138 { name => 'Load plugin (explicit path)',
1139 switches => [ '-P', 'App::Prove::Plugin::Dummy', $dummy_test ],
1141 argv => [qw( one two three )],
1144 plugins => ['Dummy'],
1147 my @loaded = get_import_log();
1148 is_deeply \@loaded, [ ['App::Prove::Plugin::Dummy'] ],
1163 { name => 'Load plugin (args + call load method)',
1164 switches => [ '-P', 'Dummy2=fou,du,fafa', $dummy_test ],
1166 argv => [qw( one two three )],
1169 plugins => ['Dummy2'],
1172 my @import = get_import_log();
1174 [ [ 'App::Prove::Plugin::Dummy2', 'fou', 'du', 'fafa' ] ],
1177 my @loaded = get_plugin_load_log();
1178 is( scalar @loaded, 1, 'Plugin->load called OK' );
1179 my ( $plugin_class, $args ) = @{ shift @loaded };
1180 is( $plugin_class, 'App::Prove::Plugin::Dummy2',
1181 'plugin_class passed'
1184 $args->{app_prove}, 'App::Prove',
1185 'app_prove object passed'
1188 $args->{args}, [qw( fou du fafa )],
1189 'expected args passed'
1204 { name => 'Load module',
1205 switches => [ '-M', 'App::Prove::Plugin::Dummy', $dummy_test ],
1207 argv => [qw( one two three )],
1210 plugins => ['Dummy'],
1213 my @loaded = get_import_log();
1214 is_deeply \@loaded, [ ['App::Prove::Plugin::Dummy'] ],
1230 # Hmm, that doesn't work...
1231 # { name => 'Switch -h',
1233 # argv => [qw( one two three )],
1235 # switches => [ '-h', $dummy_test ],
1246 # { name => 'Switch --help',
1248 # argv => [qw( one two three )],
1250 # switches => [ '--help', $dummy_test ],
1259 # { name => 'Switch -?',
1261 # argv => [qw( one two three )],
1263 # switches => [ '-?', $dummy_test ],
1273 # { name => 'Switch -H',
1275 # argv => [qw( one two three )],
1277 # switches => [ '-H', $dummy_test ],
1287 # { name => 'Switch --man',
1289 # argv => [qw( one two three )],
1291 # switches => [ '--man', $dummy_test ],
1301 # { name => 'Switch -V',
1303 # argv => [qw( one two three )],
1305 # switches => [ '-V', $dummy_test ],
1315 # { name => 'Switch --version',
1317 # argv => [qw( one two three )],
1319 # switches => [ '--version', $dummy_test ],
1329 # { name => 'Switch --color!',
1331 # argv => [qw( one two three )],
1333 # switches => [ '--color!', $dummy_test ],
1343 { name => 'Switch -I=s@',
1345 argv => [qw( one two three )],
1347 switches => [ '-Ilib', $dummy_test ],
1350 my ( $val, $attr ) = @_;
1354 && $val->[0] =~ /lib$/;
1359 # { name => 'Switch -a',
1361 # argv => [qw( one two three )],
1363 # switches => [ '-a', $dummy_test ],
1373 # { name => 'Switch --archive=-s',
1375 # argv => [qw( one two three )],
1377 # switches => [ '--archive=-s', $dummy_test ],
1387 # { name => 'Switch --formatter=-s',
1389 # argv => [qw( one two three )],
1391 # switches => [ '--formatter=-s', $dummy_test ],
1401 # { name => 'Switch -e',
1403 # argv => [qw( one two three )],
1405 # switches => [ '-e', $dummy_test ],
1415 # { name => 'Switch --harness=-s',
1417 # argv => [qw( one two three )],
1419 # switches => [ '--harness=-s', $dummy_test ],
1432 ########################################################################
1435 for my $test (@SCHEDULE) {
1436 $extra_plan += $test->{plan} || 0;
1437 $extra_plan += 2 if $test->{runlog};
1438 $extra_plan += 1 if $test->{switches};
1441 plan tests => @SCHEDULE * ( 3 + @ATTR ) + $extra_plan;
1445 for my $test (@SCHEDULE) {
1446 my $name = $test->{name};
1447 my $class = $test->{class} || 'FakeProve';
1449 local $ENV{HARNESS_TIMER};
1451 ok my $app = $class->new( exists $test->{args} ? $test->{args} : () ),
1452 "$name: App::Prove created OK";
1454 isa_ok $app, 'App::Prove';
1455 isa_ok $app, $class;
1457 # Optionally parse command args
1458 if ( my $switches = $test->{switches} ) {
1459 if ( my $proverc = $test->{proverc} ) {
1460 $app->add_rc_file( File::Spec->catfile( split /\//, $proverc ) );
1462 eval { $app->process_args( '--norc', @$switches ) };
1463 if ( my $err_pattern = $test->{parse_error} ) {
1464 like $@, $err_pattern, "$name: expected parse error";
1467 ok !$@, "$name: no parse error";
1471 my $expect = $test->{expect} || {};
1472 for my $attr ( sort @ATTR ) {
1473 my $val = $app->$attr();
1475 = exists $expect->{$attr}
1477 : $DEFAULT_ASSERTION{$attr};
1480 if ( 'CODE' eq ref $assertion ) {
1481 $is_ok = ok $assertion->( $val, $attr ),
1482 "$name: $attr has the expected value";
1484 elsif ( 'Regexp' eq ref $assertion ) {
1485 $is_ok = like $val, $assertion, "$name: $attr matches $assertion";
1488 $is_ok = is_deeply $val, $assertion,
1489 "$name: $attr has the expected value";
1493 diag "got $val for $attr";
1497 if ( my $runlog = $test->{runlog} ) {
1499 if ( my $err_pattern = $test->{run_error} ) {
1500 like $@, $err_pattern, "$name: expected error OK";
1502 pass for 1 .. $test->{plan};
1505 unless ( ok !$@, "$name: no error OK" ) {
1506 diag "$name: error: $@\n";
1509 my $gotlog = [ $app->get_log ];
1511 if ( my $extra = $test->{extra} ) {
1516 is_deeply $gotlog, $runlog,
1517 "$name: run results match"
1521 diag Dumper( { wanted => $runlog, got => $gotlog } );