Test-Aggregate-0.372000755001750001750 012453336671 13733 5ustar00randorando000000000000Test-Aggregate-0.372/META.json000444001750001750 364412453336671 15520 0ustar00randorando000000000000{ "abstract" : "Aggregate C<*.t> tests to make them run faster.", "author" : [ "Curtis \"Ovid\" Poe " ], "dynamic_config" : 1, "generated_by" : "Module::Build version 0.421", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Test-Aggregate", "prereqs" : { "build" : { "requires" : { "Test::Most" : "0.21", "Test::Simple" : "0.94", "Test::Trap" : "0" } }, "configure" : { "requires" : { "Module::Build" : "0.42" } }, "runtime" : { "recommends" : { "Data::Dump::Streamer" : "1.11", "Perl::Tidy" : "20060614", "Test::More" : "0.94" }, "requires" : { "FindBin" : "1.47", "Test::Harness" : "3.09", "Test::NoWarnings" : "0" } } }, "provides" : { "Test::Aggregate" : { "file" : "lib/Test/Aggregate.pm", "version" : "0.372" }, "Test::Aggregate::Base" : { "file" : "lib/Test/Aggregate/Base.pm", "version" : "0.372" }, "Test::Aggregate::Builder" : { "file" : "lib/Test/Aggregate/Builder.pm", "version" : "0.372" }, "Test::Aggregate::Nested" : { "file" : "lib/Test/Aggregate/Nested.pm", "version" : "0.372" } }, "release_status" : "stable", "resources" : { "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "url" : "https://github.com/rwstauner/test-aggregate" } }, "version" : "0.372", "x_contributors" : [ "Curtis \"Ovid\" Poe ", "Florian Ragwitz ", "Shlomi Fish ", "Randy Stauner " ] } Test-Aggregate-0.372/Makefile.PL000444001750001750 105712453336671 16045 0ustar00randorando000000000000# Note: this file was auto-generated by Module::Build::Compat version 0.4210 use ExtUtils::MakeMaker; WriteMakefile ( 'NAME' => 'Test::Aggregate', 'VERSION_FROM' => 'lib/Test/Aggregate.pm', 'PREREQ_PM' => { 'FindBin' => '1.47', 'Test::Harness' => '3.09', 'Test::Most' => '0.21', 'Test::NoWarnings' => 0, 'Test::Simple' => '0.94', 'Test::Trap' => 0 }, 'INSTALLDIRS' => 'site', 'EXE_FILES' => [], 'PL_FILES' => {} ) ; Test-Aggregate-0.372/README000444001750001750 155212453336671 14753 0ustar00randorando000000000000Test-Aggregate Aggregate .t files to make them run faster. INSTALLATION To install this module, run the following commands: perl Build.PL ./Build ./Build test ./Build install SUPPORT AND DOCUMENTATION After installing, you can find documentation for this module with the perldoc command. perldoc Test::Aggregate You can also look for information at: Search CPAN http://search.cpan.org/dist/Test-Aggregate CPAN Request Tracker: http://rt.cpan.org/NoAuth/Bugs.html?Dist=Test-Aggregate AnnoCPAN, annotated CPAN documentation: http://annocpan.org/dist/Test-Aggregate CPAN Ratings: http://cpanratings.perl.org/d/Test-Aggregate COPYRIGHT AND LICENCE Copyright (C) 2007 Curtis "Ovid" Poe This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Test-Aggregate-0.372/.mailmap000444001750001750 10112453336671 15461 0ustar00randorando000000000000Randy Stauner Test-Aggregate-0.372/Changes000444001750001750 2741112453336671 15410 0ustar00randorando000000000000Revision history for Test-Aggregate 0.372 2015-01-07 - Add 'no_generate_plan' option to Test::Aggregate::Nested. Thanks to David D Lowe for the pull request (gh-3 and rt-100246). 0.371 2013-09-23 - Fix bug in our test suite that failed to count enough diagnostics when run under verbose mode. Closes rt-88912 (and http://bugs.debian.org/724297). Thanks to gregor herrmann, Debian Perl Group for reporting. 0.370 2013-09-01 - Fix interpolation bug that could cause 'Unrecognized escape' warning on some platforms. - Skip nested fork test on Windows. 0.369 2013-08-25 - Don't print warning when exit() is called if it's called from a child process (if the pid has changed), since it seems likely that if the process has forked the child is expected to exit in some way. - Reformat dates in change log to appease CPAN::Changes. Thanks, Neil Bowers. 0.368 2013-08-14 - Fix tests on windows 0.367 2013-08-13 - Improve Test::Aggregate::Nested error handling: Don't treat undef as a failure; Show a warning and let Test::More::subtest() determine the result. This solves the false negative reported in https://rt.cpan.org/Public/Bug/Display.html?id=87240 Thanks to the venerable Andreas J. König for reporting! - Add more tests. - Actually include previously added tests to the dist (Where are you Dist::Zilla?) 0.366 2013-07-11 - Update metadata; Re-release to reindex with additional permissions 0.365 2013-07-10 - Avoid printing unnecessary "ok - "'s diag()s when they are passing, and when the 'verbose' option is set to 0. - The problem was that the $verbose option was hard-coded as '2' deep inside the module. - Catch errors in tests under Test::Aggregate::Nested; report as ok(0) - Pod fixes - Update repository metadata 0.364 2010-12-04 - Allow skipping the rest of a test using plan skip_all => $reason 0.363 2009-11-24 - Pass current test name to setup and teardown. 0.362 2009-11-17 - Removed broken "check_plan" from Test::Aggregate. It was always dodgy and really doesn't contribute much and the latest release broke with 'no_plan'. We now warn if we see this. - Minimum Test::More is now 0.94. This gives us more robust nested TAP. 0.361 2009-10-20 - Keep Makefile.PL in synch. Reported by Andreas Koenig (https://rt.cpan.org/Ticket/Display.html?id=50673) 0.36 2009-10-18 - Mark for production. - Removed 'dump.t' files in tests. - Improve Test::Aggregate::Nested docs. - Removed some dead code. - Suppress multiple plans (#48352, Chisel Wright) 0.35_07 2009-08-19 - Added missing files to MANIFEST. 0.35_06 2009-06-28 - Added support for nested TAP via Test::Aggregate::Nested. - I really, really need to get a real release out. 0.35_05 2009-05-20 - Removed bogus test file throwing my counts off. No wonder all tests were failing for people! - Remove development lib links. 0.35_04 Not Released - Unlink dump files in tests. 0.35_03 2009-05-15 - Don't run done_testing() in tests if it doesn't exist. 0.35_02 2009-05-14 - Deprecate tests run in BEGIN/END/CHECK/INIT. See http://use.perl.org/~Ovid/journal/38974 for more information. - check_plan, if set, is now done at the end of each test instead of the end of all tests. - Make it work with the Test::Builder 0.88 and previous versions. - Embed the calling test script name in a comment at the top of the dump file. - Fix a doc typo (thanks to Offer Kaye for the report) - Cleaned up some tests. 0.35_01 2008-11-18 - Make 'exit()' scream loudly if called. - Move Test::Aggregate::Builder globals into a hashref in the object. Further encapsulation to come later. - Export &run_this_test_program from Test::Aggregate to make dump files cleaner. - Reorganize the test suite to avoid false negatives. 0.35 2008-10-27 - Move from developer to production version number. - Add 'use Test::Aggregate' to the dump file. - Updated the docs to explain that the C functions are re-exported. 0.34_09 2008-10-15 - Added 'tests' key to the constructor. This is an optional method of identifying which tests you wish to aggregate. 0.34_08 2008-10-14 - Much refactoring of internals. This moves some autogenerated code directly into the Test::Aggregate namespace and Test::Aggregate->run calls this code directly to better synchronize behavior between running the code and running the dump file. This has the side effect of making individual test files much easier to find and read and makes the 'dump.t' file smaller. - Fixed a bug where a test dieing could cause the wrong test to be reported as failing. - Removed %INC from the list of localized variables. Localazing this doesn't remove the code from the symbol tables, so attempting to later reload this code leads to strange failures. 0.34_07 2008-10-13 - Fixed bug where dump file tests would fail if check_plan is set to true. - Common environment variables are now localized on a "per test file" basis. - Make the "5.006" requirement explicit in the Build.PL and Makefile.PL scripts. 0.34_06 2008-09-21 - Skip findbin test if FindBin < 1.47. Seems to cause test failures as FindBin *appears* to be getting confused by the setting of $0, but I'm not sure yet as I don't have an older Perl installed. 0.34_05 2008-09-19 - Changed 'unlink dump.t or die' to a warn (tests only). 0.34_03 2008-09-18 - Fixed major regression where --dry was eliminated and test counts (X of Y tests) were eliminated. - Automatically build a proper Makefile.PL. - Add FindBin to the dependencies. - Major refactoring of internals to make debugging dump files much cleaner and easier (and reduce their size, while we're at it). 0.34_03 2008-09-15 - Again cleaned up dump file generated when running tests. Need to guard against that better. Also removed it from the MANIFEST. 0.34_02 2008-09-14 - Allow skip_all tests. 0.34_01 2008-09-04 - Add an option to reinitialize FindBin for each aggregated test. - Don't emit a plan when not running any tests. 0.33 2008-09-03 - Upload 0.32_05 as a non-development release. 0.32_02 2008-08-03 - Added Test::Aggregate::Builder to the MANIFEST. 0.32_01 2008-08-03 - Added line directives to aggregated tests to ensure that Test::Builder::ok can now report the correct filename and line number. - set_filenames => 1 is now the default behavior. - Split the Test::Builder override into its own package. 0.31 2008-07-22 - Minor bugfix to play well with Test::Most (reset test failure when forcing failure after test program eval). 0.30 2008-07-17 - Resolved final (known) bug with Test::NoWarnings. If it's loaded before the plan is set, make sure we still adjust the plan. 0.24 2008-07-15 - Document the 'local $@' problem in "COMMON PITFALLS". - Ensure that dump file also forces a failure outside the eval(). - Make sure that the TEST_AGGREGATE environment variable is set in a BEGIN block. Otherwise, code relying on this variable might get called too soon to check it. 0.23 2008-06-12 - Reluctantly added Test::NoWarnings as a dependency to avoid test failures. 0.22 2008-06-11 - If we really do have an error from the eval listed below, make sure we have a failing test to accompany it. Otherwise, tests which die might be reported as passing. 0.21 2008-06-11 - Wrap ->run_the_tests() calls in an eval so that one package failing is less likely to stop the other tests from running. 0.20 2008-04-04 - 'startup' and 'shutdown' are no longer called in BEGIN/END blocks. They were getting rather tricky due to timing issues. This may change in the future. - Added 'check_plan' attribute. This allows us to verify the plan of those test programs which have one (experimental). - Added 'test_nowarnings' attribute. This can be used to disable C. - Reworked some of the Test::Builder changes to minimize the amount of monkey patching and to make the intent clearer. - Verbosity is now 0, 1, or 2. If '1' is verbosity, we only show test failures. - We now maintain the Build.PL and Makefile.PL files separately due to issues with the latter not supporting the features of the former. - Eliminated some bogus tests added which were only there to show you which aggtest was being run. - Fixed the dates in the Changes file. 0.11 2008-03-15 - Fixed bug where not having Data::Dump::Streamer installed would cause test failures if 'dump' was not set. Reported by numerous CPAN smoke testers :) - Added optional (and experimental) Perl::Tidy support. - Fixed broken 'verbose'. The 'ok/not ok' message was being output regardless of verbose setting. 0.10 2008-03-13 - Added startup, shutdown, setup, teardown attributes. - Add more tests. - Clean up dump file generated by tests. 0.08 2008-03-09 - Require Test::Builder 0.74. - We now diag ok/not ok messages for each test program. This makes it much easier to figure out which program failed. - Fixed warnings when 'dump' was not set. Thanks to RENEEB for the bug report [http://rt.cpan.org/Ticket/Display.html?id=32443] 0.07 2008-03-05 - Added TEST_AGGREGATE environment variable. 0.06 2008-01-15 - Use an END block instead of adding Test::Builder::DESTROY. This is cleaner and doesn't override the DESTROY provided by Test::Most. 0.05 2007-12-29 - Fixed an open in aggtests/boilerplate.t which made the module fail with 5.005. 0.04 2007-12-29 - Fixed open() to work with versions of Perl < 5.6 - More extensive overriding of Test::Builder internals. I tried to subclass it but it's not designed to be subclassed and much pain ensued. - Dump file now has all "run_the_tests" lines at the top and the packages below them. This makes for easier debugging as you can comment out test packages one by one simply by commenting out its "run_the_tests" line. - Fixed bug where runtests() would run tests in a different order from the dump file. - Fixed bug where Test::NoWarnings would try to run a test after the plan was output. 0.03 2007-11-29 - Moved 'skip_all' files into the t/ directory. Aggregating them fails. mauzo (http://use.perl.org/~mauzo/) 0.02 2007-11-26 - Fixed bug where multiple tests setting an explicit plan in the use statement would cause failures. - Attempt to work around 'unauthorized release' issue on the CPAN. Simply declaring the 'Test::Builder' package directly is frowned upon. - Update the docs to warn explain 'shared variable' warnings. 0.01 2007-11-25 First version. Run test suites faster. Test-Aggregate-0.372/Build.PL000444001750001750 272312453336671 15370 0ustar00randorando000000000000# git ls-files lib | xargs perl-reversion -bump # perl Build.PL && ./Build manifest && ./Build test && ./Build dist # cpan-upload `ls Test-Aggregate-*.tar.gz | tail -n1` # git tag `awk '/^version: / { print " -a " $2 " -m " $2 }' META.yml` && git push && git push --tags use strict; use warnings; use Module::Build; use 5.006; my $builder = Module::Build->new( module_name => 'Test::Aggregate', license => 'perl', dist_author => 'Curtis "Ovid" Poe ', dist_version_from => 'lib/Test/Aggregate.pm', build_requires => { 'Test::Simple' => 0.94, # we fail on the common 0.62 'Test::Most' => 0.21, 'Test::Trap' => 0, }, requires => { 'Test::Harness' => 3.09, 'Test::NoWarnings' => 0, 'FindBin' => 1.47, }, recommends => { 'Data::Dump::Streamer' => 1.11, 'Perl::Tidy' => 20060614, 'Test::More' => '0.94', }, meta_merge => { resources => { repository => "https://github.com/rwstauner/test-aggregate", }, x_contributors => [ 'Curtis "Ovid" Poe ', 'Florian Ragwitz ', 'Shlomi Fish ', 'Randy Stauner ', ], }, add_to_cleanup => ['Test-Aggregate-*'], create_makefile_pl => 'traditional', ); $builder->create_build_script(); Test-Aggregate-0.372/MANIFEST000444001750001750 156312453336671 15226 0ustar00randorando000000000000.mailmap aggtests-extras/die.t aggtests-extras/fake_read_failure.t aggtests-extras/fork_and_exit.t aggtests-extras/skip_to_end_undefined.t aggtests-nested/data_handle.t aggtests-nested/number_of_tests.t aggtests/check_plan.t aggtests/done_testing.t aggtests/findbin.t aggtests/no_plan.t aggtests/plan_skip_all.t aggtests/skip_all.t aggtests/skip_to_end.t aggtests/slow_load.t aggtests/subs.t Build.PL Changes lib/Test/Aggregate.pm lib/Test/Aggregate/Base.pm lib/Test/Aggregate/Builder.pm lib/Test/Aggregate/Nested.pm Makefile.PL MANIFEST META.json META.yml # Will be created by "make dist" README t/00-load.t t/aggregate.t t/exception.t t/fork_and_exit.t t/lib/AggTestTester.pm t/lib/Slow/Loading/Module.pm t/nested.t t/nested_no_generate_plan.t t/nested_skip_to_end.t t/pre_post.t t/pre_post_nested.t t/read_failure.t t/subs.t t/verbose.t xt/author/pod-coverage.t xt/author/pod.t Test-Aggregate-0.372/META.yml000444001750001750 236412453336671 15346 0ustar00randorando000000000000--- abstract: 'Aggregate C<*.t> tests to make them run faster.' author: - 'Curtis "Ovid" Poe ' build_requires: Test::Most: '0.21' Test::Simple: '0.94' Test::Trap: '0' configure_requires: Module::Build: '0.42' dynamic_config: 1 generated_by: 'Module::Build version 0.421, CPAN::Meta::Converter version 2.143240' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Test-Aggregate provides: Test::Aggregate: file: lib/Test/Aggregate.pm version: '0.372' Test::Aggregate::Base: file: lib/Test/Aggregate/Base.pm version: '0.372' Test::Aggregate::Builder: file: lib/Test/Aggregate/Builder.pm version: '0.372' Test::Aggregate::Nested: file: lib/Test/Aggregate/Nested.pm version: '0.372' recommends: Data::Dump::Streamer: '1.11' Perl::Tidy: '20060614' Test::More: '0.94' requires: FindBin: '1.47' Test::Harness: '3.09' Test::NoWarnings: '0' resources: license: http://dev.perl.org/licenses/ repository: https://github.com/rwstauner/test-aggregate version: '0.372' x_contributors: - 'Curtis "Ovid" Poe ' - 'Florian Ragwitz ' - 'Shlomi Fish ' - 'Randy Stauner ' Test-Aggregate-0.372/aggtests000755001750001750 012453336671 15554 5ustar00randorando000000000000Test-Aggregate-0.372/aggtests/skip_to_end.t000444001750001750 36712453336671 20362 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use Test::More; SKIP: { { # Do this just to get $! set. open(my $fh, '<', 'a-file-that-almost-certainly-does.not.exist'); } skip 'to end', 1; } # Return a defined value. 0; Test-Aggregate-0.372/aggtests/plan_skip_all.t000444001750001750 26612453336671 20672 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use lib 'lib', 't/lib'; use Test::More; ok 1, 'Should be reached'; plan skip_all => 'Testing skip all'; ok 0, 'Should not reach here'; Test-Aggregate-0.372/aggtests/skip_all.t000444001750001750 22312453336671 17651 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use lib 'lib', 't/lib'; use Test::More skip_all => 'Testing skip all'; ok 0, 'Should not reach here'; Test-Aggregate-0.372/aggtests/check_plan.t000444001750001750 53012453336671 20143 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use lib 'lib', 't/lib'; use Test::More tests => 5; ok 1, "$0 ***** 1"; ok 1, "$0 ***** 2"; SKIP: { skip "checking plan ($0 ***** 3)", 1; ok 1; } ok !exists $ENV{aggregated_current_script}, 'env variables should not hang around'; ok 1, "$0 ***** 4"; $ENV{aggregated_current_script} = $0; Test-Aggregate-0.372/aggtests/done_testing.t000444001750001750 21612453336671 20537 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use lib 'lib', 't/lib'; use Test::More; ok 1, "$0 ***** 1"; ok 1, "$0 ***** 2"; done_testing(); Test-Aggregate-0.372/aggtests/no_plan.t000444001750001750 20712453336671 17503 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use lib 'lib', 't/lib'; use Test::More 'no_plan'; ok 1, "$0 ***** 1"; ok 1, "$0 ***** 2"; Test-Aggregate-0.372/aggtests/slow_load.t000444001750001750 43312453336671 20041 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use lib 'lib', 't/lib'; use Test::More tests => 2; use Slow::Loading::Module; ok 1, 'slow loading module loaded'; ok !exists $ENV{aggregated_current_script}, 'env variables should not hang around'; $ENV{aggregated_current_script} = $0; Test-Aggregate-0.372/aggtests/findbin.t000444001750001750 51512453336671 17470 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use Test::More tests => 1; use FindBin; use File::Spec::Functions qw/rel2abs catfile/; SKIP: { skip "FindBin version too low", 1 if FindBin->VERSION < 1.47; is( rel2abs( catfile( $FindBin::Bin, 'findbin.t' ) ), rel2abs($0), 'findbin is reinitialized for every test' ); } Test-Aggregate-0.372/aggtests/subs.t000444001750001750 35112453336671 17031 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use lib 'lib', 't/lib'; use Test::More tests => 1; use Slow::Loading::Module; { no warnings; my $whee = 'whee!'; sub whee { return $whee } } is whee(), 'whee!', 'subs work!'; Test-Aggregate-0.372/xt000755001750001750 012453336671 14366 5ustar00randorando000000000000Test-Aggregate-0.372/xt/author000755001750001750 012453336671 15670 5ustar00randorando000000000000Test-Aggregate-0.372/xt/author/pod-coverage.t000444001750001750 42112453336671 20542 0ustar00randorando000000000000#!perl -T use strict; use warnings; use Test::More; eval 'use Test::Pod::Coverage 1.04'; plan skip_all => 'Test::Pod::Coverage 1.04 required for testing POD coverage' if $@; plan tests => 1; pod_coverage_ok( 'Test::Aggregate', { trustme => [ qr/(?:no_header|plan)/ ] } ); Test-Aggregate-0.372/xt/author/pod.t000444001750001750 24612453336671 16756 0ustar00randorando000000000000#!perl -T use strict; use warnings; use Test::More; eval 'use Test::Pod 1.14'; plan skip_all => 'Test::Pod 1.14 required for testing POD' if $@; all_pod_files_ok(); Test-Aggregate-0.372/t000755001750001750 012453336671 14176 5ustar00randorando000000000000Test-Aggregate-0.372/t/fork_and_exit.t000444001750001750 114412453336671 17334 0ustar00randorando000000000000use strict; use warnings; use Test::More tests => 2; # 1 in agg test, 1 subtest use lib 't/lib'; use AggTestTester; my $args = { tests => [catfile(qw(aggtests-extras fork_and_exit.t))], }; Test::Aggregate->new({%$args})->run; SKIP: { # The nested fork test crashes on windows. # I have no idea why and I don't care enough # to spend any more time trying to figure it out. # If you know or care, patches are most welcome. skip('Skip nested fork test on windows', 1) if $^O eq 'MSWin32'; only_with_nested { subtest nested => sub { Test::Aggregate::Nested->new({%$args})->run; }; }; } Test-Aggregate-0.372/t/verbose.t000444001750001750 113612453336671 16166 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use Test::More tests => 1; use Test::Trap qw( trap $trap :flow:stderr(systemsafe):stdout(systemsafe):warn ); trap { system($^X, '-e', <<'EOF'); use lib 'lib', 't/lib'; use Test::Aggregate; my $dump = 'dump.t'; my $tests = Test::Aggregate->new( { dirs => 'aggtests', verbose => 0,} ); $tests->run; EOF }; my $stderr = $trap->stderr(); unlike ($stderr, qr{^\#\s*ok\s+-\s+aggtests/}ms, 'With verbose => 0, no traces of ok are shown.' ); #ok -f $dump, '... and we should have written out a dump file'; #unlink $dump or warn "Cannot unlink ($dump): $!"; Test-Aggregate-0.372/t/exception.t000444001750001750 145012453336671 16516 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use Test::More; use lib 't/lib'; use AggTestTester; my $dir = 'aggtests-extras'; my @agg_tests = qw( die ); my @agg_paths = map { catfile($dir, "$_.t") } @agg_tests; my @exp_results = ( # The test starts with an ok(1). [ 1, qr{$dir.die\.t \*\*\*\*\* 1}, 'Ran die.t', ], # This is the important one: [ 0, qr/Ensure exceptions are not hidden during aggregate tests/, "Exception shown as ok(0)", ], ); aggregate('Test::Aggregate', \@agg_paths, \@exp_results); only_with_nested { push @exp_results, ( # Nested will add the parent 'ok' for the subtest. [ 1, qr{Tests for $dir.die\.t}, 'Subtest completed for die.t', ], ); aggregate('Test::Aggregate::Nested', \@agg_paths, \@exp_results); }; done_testing; Test-Aggregate-0.372/t/aggregate.t000444001750001750 45512453336671 16432 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use lib 'lib', 't/lib'; use Test::Aggregate; my $dump = 'dump.t'; my $tests = Test::Aggregate->new( { dirs => 'aggtests', } ); $tests->run; #ok -f $dump, '... and we should have written out a dump file'; #unlink $dump or warn "Cannot unlink ($dump): $!"; Test-Aggregate-0.372/t/pre_post_nested.t000444001750001750 252712453336671 17723 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use lib 'lib', 't/lib'; use Test::More; plan +Test::More->can('subtest') ? ( tests => 6 ) : ( skip_all => 'Need Test::More::subtest() for this test' ); use Test::Aggregate::Nested; my ( $startup, $shutdown ) = ( 0, 0 ); my ( $setup, $teardown ) = ( 0, 0 ); $SIG{__WARN__} = sub { my $warning = shift; if ( $warning =~ m{Can't locate Data/Dump/Streamer\.pm in \@INC} ) { #' return; } CORE::warn($warning); }; my $found_it; subtest 'nested tests' => sub { my $tests = Test::Aggregate::Nested->new( { dirs => 'aggtests', findbin => 1, startup => sub { $startup++ }, shutdown => sub { $shutdown++ }, setup => sub { my $file = shift; if ( $file =~ /slow_load\.t$/ ) { $found_it = 1; } $setup++; }, teardown => sub { $teardown++ }, shuffle => 1, } ); $tests->run; }; my $num_tests = 9; is $startup, 1, 'Startup should be called once'; is $shutdown, 1, '... as should shutdown'; is $setup, $num_tests, 'Setup should be called once for each test program'; is $teardown, $num_tests, '... as should teardown'; ok $found_it, '... and file names should be passed to setup'; Test-Aggregate-0.372/t/nested_skip_to_end.t000444001750001750 136512453336671 20365 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use lib 't/lib'; use AggTestTester; use Test::More; only_with_nested { aggregate( 'Test::Aggregate::Nested', [ catfile('aggtests-extras', 'fake_read_failure.t'), catfile('aggtests-extras', 'skip_to_end_undefined.t'), catfile('aggtests', 'skip_to_end.t'), ], [ [ 0, qr/No tests run/, 'read failure results in failed test' ], [ 1, qr/Tests for .+?\bskip_to_end_undefined\.t/, 'skipped to end' ], [ 1, qr/Tests for .+?\bskip_to_end\.t/, 'skipped to end' ], ], diag => [ qr/ unknown if .+?\bfake_read_failure\.t.+? actually finished.+? error was set \(\$!\):/sm, qr/No tests run/, ], ); }; done_testing; Test-Aggregate-0.372/t/read_failure.t000444001750001750 223212453336671 17141 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use Test::More; use lib 't/lib'; use AggTestTester; my $path = catfile(qw(aggtests-does-not-exist no-really-it-should-not-exist.t)); { my $run = eval { aggregate('Test::Aggregate', [$path], []); 1; }; my $e = $@; is $run, undef, 'run failed (expectedly)'; like $@, qr/^Cannot read .\Q$path\E./, 'Instant death for file that does not exist'; } only_with_nested { my $gen_exp_results = sub { my $path = shift; return ([ [ 0, qr/No tests run for subtest .+?\Q$path\E/, "Read failure results in failed test", ] ], diag => [ qr/unknown if .+?\Q$path\E.+? actually finished/, qr/No tests run/, ], ); }; # A file that doesn't exist. aggregate('Test::Aggregate::Nested', [$path], $gen_exp_results->($path), # Re-running FindBin will die because the file doesn't exist, so don't. findbin => 0, ); # Simulate a file that does exist but fails to read for some other reason. $path = catfile(qw(aggtests-extras fake_read_failure.t)); aggregate('Test::Aggregate::Nested', [$path], $gen_exp_results->($path)); }; done_testing; Test-Aggregate-0.372/t/pre_post.t000444001750001750 226312453336671 16356 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use lib 'lib', 't/lib'; use Test::Aggregate; my ( $startup, $shutdown ) = ( 0, 0 ); my ( $setup, $teardown ) = ( 0, 0 ); $SIG{__WARN__} = sub { my $warning = shift; if ( $warning =~ m{Can't locate Data/Dump/Streamer\.pm in \@INC} ) { #' return; } CORE::warn($warning); }; my $dump = 'dump.t'; my $found_it; my $tests = Test::Aggregate->new( { dirs => 'aggtests', findbin => 1, startup => sub { $startup++ }, shutdown => sub { $shutdown++ }, setup => sub { my $file = shift; if ( $file =~ /slow_load\.t$/ ) { $found_it = 1; } $setup++; }, teardown => sub { $teardown++ }, # dump => $dump, } ); $tests->run; my $num_tests = 9; is $startup, 1, 'Startup should be called once'; is $shutdown, 1, '... as should shutdown'; is $setup, $num_tests, 'Setup should be called once for each test program'; is $teardown, $num_tests, '... as should teardown'; #unlink $dump or warn "Cannot unlink ($dump): $!"; ok $found_it, '... and file names should be passed to setup'; done_testing(); Test-Aggregate-0.372/t/nested.t000444001750001750 116312453336671 16003 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use lib 'lib', 't/lib'; use Test::Aggregate::Nested; use Test::More; plan skip_all => 'Need Test::More::subtest() for this test' unless Test::More->can('subtest'); my $dump = 'dump.t'; my $tests = Test::Aggregate::Nested->new( { verbose => 2, shuffle => 1, dirs => [ 'aggtests', 'aggtests-nested' ], set_filenames => 1, findbin => 1, test_nowarnings => 0, } ); $tests->run; #ok -f $dump, '... and we should have written out a dump file'; #unlink $dump or warn "Cannot unlink ($dump): $!"; Test-Aggregate-0.372/t/nested_no_generate_plan.t000444001750001750 112112453336671 21355 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use lib 'lib', 't/lib'; use Test::Aggregate::Nested; use Test::More; plan skip_all => 'Need Test::More::subtest() for this test' unless Test::More->can('subtest'); my $dump = 'dump.t'; my $tests = Test::Aggregate::Nested->new( { verbose => 2, shuffle => 1, dirs => [ 'aggtests', 'aggtests-nested' ], set_filenames => 1, findbin => 1, test_nowarnings => 0, no_generate_plan => 1, } ); $tests->run; ok(1, "A test at the end"); done_testing(); Test-Aggregate-0.372/t/00-load.t000555001750001750 63012453336671 15636 0ustar00randorando000000000000#!perl use Test::More tests => 3; use lib 't/lib'; BEGIN { use_ok('Test::Aggregate') or die; use_ok('Slow::Loading::Module') or die; } diag("Testing Test::Aggregate $Test::Aggregate::VERSION, Perl $], $^X"); diag("... with Test::Builder $Test::Builder::VERSION"); ok !exists $ENV{aggregated_current_script}, 'env variables should not hang around'; $ENV{aggregated_current_script} = $0; Test-Aggregate-0.372/t/subs.t000444001750001750 76512453336671 15464 0ustar00randorando000000000000#!/usr/bin/perl #use lib '../Test-Simple-0.86/lib'; use strict; use warnings; use lib 'lib', 't/lib'; use Test::Aggregate; my $dump = 'done_testing.t'; my $tests = Test::Aggregate->new( { dirs => 'aggtests', matching => qr/subs/, # dump => $dump, } ); $tests->run; my $tests_run = Test::Builder->new->current_test; is $tests_run, 1, '... and we should only run as many tests as are in the matching tests'; #unlink $dump or warn "Cannot unlink ($dump): $!"; Test-Aggregate-0.372/t/lib000755001750001750 012453336671 14744 5ustar00randorando000000000000Test-Aggregate-0.372/t/lib/AggTestTester.pm000444001750001750 676312453336671 20200 0ustar00randorando000000000000# vim: set ft=perl ts=2 sts=2 sw=2 et sta: use strict; use warnings; package # no_index AggTestTester; use Test::Aggregate; use File::Spec::Functions qw(catfile); # core use Test::More; use Exporter; our @ISA = qw(Exporter); our @EXPORT = qw( aggregate catfile only_with_nested ); sub only_with_nested (&) { my $sub = shift; SKIP: { # We use done_testing so skip(1) is sufficient. skip 'Need Test::More::subtest() for nested tests', 1 if !Test::More->can('subtest'); require Test::Aggregate::Nested; $sub->(); } } sub aggregate { AggTestTester->new(@_)->run; } sub new { my ($class, $mod, $tests, $exp, %extra) = @_; eval "require $mod" or die $@; bless { mod => $mod, tests => $tests, exp => $exp, diag => delete($extra{diag}) || [], args => { %extra }, }, $class; } sub aggregator { my ($self) = shift; return $self->{mod}->new({ tests => $self->{tests}, verbose => 2, %{ $self->{args} }, @_, }); } sub run { my $self = shift; my $mod = $self->{mod}; my $is_nested = ($mod =~ /::Nested$/); my $tb = {}; my @ran; # Break the reference. my @exp_results = @{ $self->{exp} }; # Test::Tester didn't work well with Test::Aggregate # so just override the functions used in the tests { no strict 'refs'; no warnings 'redefine'; # Keep copies to the originals so we can call them. my $ok = \&Test::Builder::ok; my $diag = \&Test::Builder::diag; # Intercept calls to ok(): # Make it "ok" if it's the test we expected and "not ok" if it isn't. local *Test::Builder::ok = sub { my ($self, $val, $msg) = @_; my $agg_ok = 0; my $exp = $exp_results[0]; if( $exp && $val == $exp->[0] && $msg =~ $exp->[1] ){ $agg_ok = 1; $msg = $exp->[2]; shift @exp_results; } # For debugging. if( !$agg_ok ){ $self->$diag( "Intercepted: ok($val, $msg);"); $self->$diag($exp ? "Expected: ok($exp->[0], $exp->[1]);" : "No more expected"); } $self->$ok($agg_ok, "(Aggregated) $msg"); }; # Hide most diag output, but track it for later. local *Test::Builder::diag = sub { my ($self, $msg) = @_; push @{ $tb->{diag} }, $msg; }; my $agg = $self->aggregator( setup => sub { push @ran, $_[0] }, ); # Nested sets a plan so it needs to run in a subtest. if( $is_nested ){ # Therefore we'll need to expect another ok(). push @exp_results, [1, qr/Nested/, 'Tester subtest']; Test::More::subtest(Nested => sub { $agg->run }) } else { $agg->run; } } is scalar(@exp_results), 0, "$mod - All expected tests found"; is_deeply(\@ran, $self->{tests}, "$mod - All expected test scripts run"); # Check diag to see that we ran each script. # This is redundant with the setup block test but it makes me feel good. my @exp_diags = ( (map { ( (!$is_nested && $ENV{TEST_VERBOSE} ? qr/[*]{8} running tests for \Q$_\E [*]{8}/ : ()), qr/ \Q$_\E \(\d out of ${\scalar @{ $self->{tests} }}\)/, ) } @{ $self->{tests} }), @{ $self->{diag} }, ); my @diags = @{ $tb->{diag} }; my @unmatched; is scalar(@exp_diags), scalar(@diags), 'expected number of diagnostics'; DIAG: while( my $diag = shift @diags ){ foreach my $exp_msg ( @exp_diags ){ $diag =~ $exp_msg and next DIAG; } push @unmatched, $diag; } is scalar(@unmatched), 0, 'all diagnostics matched' or diag explain \@unmatched; } 1; Test-Aggregate-0.372/t/lib/Slow000755001750001750 012453336671 15670 5ustar00randorando000000000000Test-Aggregate-0.372/t/lib/Slow/Loading000755001750001750 012453336671 17245 5ustar00randorando000000000000Test-Aggregate-0.372/t/lib/Slow/Loading/Module.pm000444001750001750 5512453336671 21125 0ustar00randorando000000000000package Slow::Loading::Module; sleep 1; 1; Test-Aggregate-0.372/aggtests-extras000755001750001750 012453336671 17060 5ustar00randorando000000000000Test-Aggregate-0.372/aggtests-extras/fork_and_exit.t000444001750001750 66612453336671 22206 0ustar00randorando000000000000use strict; use warnings; use Test::More; SKIP: { defined(my $pid = fork) or skip("Fork failed: $!", 1); # parent if( $pid ){ diag "# parent => $$, child => $pid\n"; ok(1, 'forked'); } # child else { diag "No warning for child exit...\n"; exit(); } # Slow down so the child prints first #select(undef, undef, undef, 0.25); #diag "Calling exit() in parent produces warning:\n"; #exit(); } 0; Test-Aggregate-0.372/aggtests-extras/skip_to_end_undefined.t000444001750001750 47112453336671 23703 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use Test::More 'no_plan'; SKIP: { { # Do this just to get $! set. open(my $fh, '<', 'a-file-that-almost-certainly-does.not.exist'); } skip 'to end', 1; } # Don't return a value, the 'last skip' should jump out # so the file returns undef. Test-Aggregate-0.372/aggtests-extras/die.t000444001750001750 24112453336671 20120 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use Test::More; ok 1, "$0 ***** 1"; die "Ensure exceptions are not hidden during aggregate tests"; done_testing(); Test-Aggregate-0.372/aggtests-extras/fake_read_failure.t000444001750001750 25512453336671 22774 0ustar00randorando000000000000# Simulate a test script that exists but fails to read: # Set $! accordingly and don't run any tests. { open(my $fh, '<', 'a-file-that-almost-certainly-does.not.exist'); } Test-Aggregate-0.372/lib000755001750001750 012453336671 14501 5ustar00randorando000000000000Test-Aggregate-0.372/lib/Test000755001750001750 012453336671 15420 5ustar00randorando000000000000Test-Aggregate-0.372/lib/Test/Aggregate.pm000444001750001750 6763012453336671 20035 0ustar00randorando000000000000package Test::Aggregate; use warnings; use strict; use Carp 'croak'; use Test::More; use Test::Aggregate::Base; use vars qw(@ISA @EXPORT @EXPORT_OK); @ISA = qw(Test::Aggregate::Base); @EXPORT = (@Test::More::EXPORT, 'run_this_test_program'); # controls whether or not we show individual test program pass/fail my %VERBOSE = ( none => 0, failures => 1, all => 2, ); my $BUILDER = Test::Builder->new; =encoding utf-8 =head1 NAME Test::Aggregate - Aggregate C<*.t> tests to make them run faster. =head1 VERSION Version 0.372 =cut our $VERSION = '0.372'; $VERSION = eval $VERSION; =head1 SYNOPSIS use Test::Aggregate; my $tests = Test::Aggregate->new( { dirs => $aggregate_test_dir, } ); $tests->run; ok $some_data, 'Test::Aggregate also re-exports Test::More functions'; =head1 DESCRIPTION B: this is ALPHA code. The interface is not guaranteed to be stable. Further, check out L (included with this distribution). It's a more robust implementation which does not have the same limitations as C. A common problem with many test suites is that they can take a long time to run. The longer they run, the less likely you are to run the tests. This module borrows a trick from C to load up your tests at once, create a separate package for each test and wraps each package in a method named C. This allows us to load perl only once and related modules only once. If you have modules which are expensive to load, this can dramatically speed up a test suite. =head1 DEPRECATION For a whole variety of reasons, tests run in BEGIN/CHECK/INIT/INIT blocks are now deprecated. They cause all sorts of test sequence headaches. Plus, they break the up-coming nested TAP work. You will have a problem if you use this common idiom: BEGIN { use_ok 'My::Module' or die; } Instead, just C the module and put the C tests in a t/load.t file or something similar and B aggregate it. See the following for more information: L. =head1 USAGE Create a separate directory for your tests. This should not be a subdirectory of your regular test directory. Write a small driver program and put it in your regular test directory (C is the standard): use Test::Aggregate; my $other_test_dir = 'aggregate_tests'; my $tests = Test::Aggregate->new( { dirs => $other_test_dir }); $tests->run; ok $some_data, 'Test::Aggregate also re-exports Test::More functions'; Take your simplest tests and move them, one by one, into the new test directory and keep running the C program. You'll find some tests will not run in a shared environment like this. You can either fix the tests or simply leave them in your regular test directory. See how this distribution's tests are organized for an example. Note that C also exports all exported functions from C, allowing you to run other tests after the aggregated tests have run. use Test::Aggregate; my $other_test_dir = 'aggregate_tests'; my $tests = Test::Aggregate->new( { dirs => $other_test_dir }); $tests->run; ok !(-f 't/data/tmp.txt'), '... and our temp file should be deleted'; Some tests cannot run in an aggregate environment. These may include test for this with the C<< $ENV{TEST_AGGREGATE} >> variable: package Some::Package; BEGIN { die __PACKAGE__ ." cannot run in aggregated tests" if $ENV{TEST_AGGREGATE}; } =head1 METHODS =head2 C my $tests = Test::Aggregate->new( { dirs => 'aggtests', verbose => 1, # optional, but recommended dump => 'dump.t', # optional shuffle => 1, # optional matching => qr/customer/, # optional set_filenames => 0, # optional and not recommended tidy => 1, # optional and experimental test_nowarnings => 0, # optional and experimental } ); Creates a new C instance. Accepts a hashref with the following keys: =over 4 =item * C (either this or C is mandatory) The directories to look in for the aggregated tests. This may be a scalar value of a single directory or an array refernce of multiple directories. =item * C (either this or C is mandatory) Instead of providing directories for the aggregated tests, you may supply an array reference with a list of tests to aggregate. If both are supplied, these tests will be appended to the list of tests found in C. The C parameter does not apply to test files identified with this key. =item * C (optional, but strongly recommended) If set with a true value, each test programs success or failure will be indicated with a diagnostic output. The output below means that C was an aggregated test which failed. This means it's much easier to determine which aggregated tests are causing problems. t/aggregate.........2/? # ok - aggtests/boilerplate.t # ok - aggtests/00-load.t # not ok - aggtests/subs.t # ok - aggtests/slow_load.t t/aggregate.........ok t/pod-coverage......ok t/pod...............ok Note that three possible values are allowed for C: =over 4 =item * C<0> (default) No individual test program success or failure will be displayed. =item * C<1> Only failing test programs will have their failure status shown. =item * C<2> All test programs will have their success/failure shown. =back =item * C (optional) You may list the name of a file to dump the aggregated tests to. This is useful if you have test failures and need to debug why the tests failed. =item * C (optional) Ordinarily, the tests are sorted by name and run in that order. This allows you to run them in any order. =item * C (optional) If supplied with a regular expression (requires the C operator), will only run tests whose filename matches the regular expression. =item * C (optional) If supplied with a true value, this will cause the following to be added for each test: local $0 = $test_filename; This is the default behavior. =item * C (optional) If supplied with a true value, this will cause FindBin::again() to be called before each test file. This is turned off by default. Note that older versions of FindBin (pre 1.47) sometimes get confused about where the bin directory is when I set C<$0>. I don't know why, but this is a rarely used option and only happens pre 5.8 perl, so I'm not too worried about it. Just keep it in mind. =item * C (optional) Just print the tests which will be run and the order they will be run in (obviously the order will be random if C is true). =item * C If supplied a true value, attempts to run C on the source code. This is a no-op if C cannot be loaded. This option is C. Plus, if your tests are terribly convoluted, this could be slow and possibly buggy. If the value of this argument is the name of a file, assumes that this file is a C<.perltidyrc> file. =item * C Disables C (fails if the module cannot be loaded). This is experimental and somewhat problematic. Let me know if there are any problems. =back =cut sub new { my $class = shift; my $self = $class->SUPER::new(@_); if ($self->{no_generate_plan}) { croak "no_generate_plan is not supported in Test::Aggregate"; } return $self; } =head2 C $tests->run; Attempts to aggregate and run all tests listed in the directories specified in the constructor. =cut sub _do_dry_run { } sub run { my $self = shift; local $Test::Aggregate::Base::_pid = $$; my $verbose = $self->_verbose; my @tests = $self->_get_tests; if ( $self->_dry ) { my $current = 1; my $total = @tests; foreach my $test (@tests) { print "$test (File $current out of $total)\n"; $current++; } return; } my $code = $self->_build_aggregate_code(@tests); my $dump = $self->_dump; if ( $dump ne '' ) { local *FH; open FH, "> $dump" or die "Could not open ($dump) for writing: $!"; print FH $code; close FH; } # XXX Theoretically the 'eval $code' could run the tests directly and # remove a lot of annoying duplication, but unfortunately, we can't # properly capture the startup/shutdown/setup/teardown behavior there # without mandating that Data::Dump::Streamer be installed. As a result, # this eval'ed code has a check to not actually run the tests if we are # not in the dump file. eval $code; if ( my $error = $@ ) { croak("Could not run tests: $@"); } $self->_startup->() if $self->_startup; # some tests may have been run in BEGIN blocks. This is deprecated and # now warns my $tab = 'Test::Aggregate::Builder'; $BUILDER->{$tab}{last_test} = @{ $BUILDER->{Test_Results} } || 0; $BUILDER->{$tab}{aggregate_program} = $self->{aggregate_program}; my $current_test = 0; my @packages = $self->_packages; my $total_tests = @packages; foreach my $data (@packages) { $current_test++; my ( $test, $package ) = @$data; $self->_setup->($test) if $self->_setup; run_this_test_program( $package => $test, $current_test, $total_tests, $verbose ); if ( my $error = $@ ) { Test::More::ok( 0, "Error running ($test): $error" ); } # XXX this should be fine since these keys are not actually used # internally. $BUILDER->{XXX_test_failed} = 0; $BUILDER->{TEST_MOST_test_failed} = 0; $self->_teardown->($test) if $self->_teardown; } $self->_shutdown->() if $self->_shutdown; } sub _any_tests_failed { my $failed = 0; my $builder = Test::Builder->new; my @summary = $builder->summary; foreach my $passed ( @summary[ $builder->{'Test::Aggregate::Builder'}{last_test} .. $builder->current_test - 1 ] ) { if (not $passed) { $failed = 1; last; } } return $failed; } sub run_this_test_program { my $builder = Test::Builder->new; my ( $package, $test, $current_test, $num_tests, $verbose ) = @_; Test::More::diag("******** running tests for $test ********") if $ENV{TEST_VERBOSE}; my $error = eval { if ( my $reason = $builder->{'Test::Aggregate::Builder'}{skip_all}{$package} ) { $builder->skip($reason); return; } else { local $@; # localize some popular globals no warnings 'uninitialized'; local %ENV = %ENV; local $/ = $/; local @INC = @INC; local $_ = $_; local $| = $|; local %SIG = %SIG; use warnings 'uninitialized'; $builder->{'Test::Aggregate::Builder'}{file_for}{$package} = $test; local $builder->{'Test::Aggregate::Builder'}{running} = $package; eval { $package->run_the_tests }; if ($@ && ref($@) && $@ == $Test::Aggregate::Builder::skip) { $builder->skip( $builder->{'Test::Aggregate::Builder'}{skip_all}{$package} ); return; } $@; } }; { my $test_name = "$test ($current_test out of $num_tests)"; my $failed = _any_tests_failed(); chomp $error if defined $error; $error &&= "($error)"; my $ok = $failed || $error ? "not ok - $test_name $error" : " ok - $test_name"; # don't diag if verbose is zero if( $verbose ){ Test::More::diag($ok) if $error or $failed or $verbose == $VERBOSE{all}; } # but do register as a failure if ($error or $failed) { Test::More::ok(0, "Error running ($test): $error"); # XXX this should be fine since these keys are not actually used # internally. $builder->{XXX_test_failed} = 0; $builder->{TEST_MOST_test_failed} = 0; } } $builder->{'Test::Aggregate::Builder'}{last_test} = $builder->current_test; return unless $error; } sub _build_aggregate_code { my ( $self, @tests ) = @_; my $code = "\n# Built from $0\n"; $code .= $self->_test_builder_override; my ( $startup, $startup_code ) = $self->_as_code('startup'); my ( $shutdown, $shutdown_code ) = $self->_as_code('shutdown'); my ( $setup, $setup_code ) = $self->_as_code('setup'); my ( $teardown, $teardown_code ) = $self->_as_code('teardown'); my $verbose = $self->_verbose; my $findbin; if ( $self->_findbin ) { $findbin = <<' END_CODE'; use FindBin; my $REINIT_FINDBIN = FindBin->can(q/again/) || sub {}; END_CODE } else { $findbin = 'my $REINIT_FINDBIN = sub {};'; } $code .= <<" END_CODE"; $startup_code $shutdown_code $setup_code $teardown_code $findbin END_CODE my @packages; my $separator = '#' x 20; my $test_packages = ''; my $dump = $self->_dump; $code .= "if ( __FILE__ eq '$dump' ) {\n"; if ( $startup ) { $code .= " $startup->() if __FILE__ eq '$dump';\n"; } my $current_test = 0; my $total_tests = @tests; foreach my $test (@tests) { $current_test++; my $test_code = $self->_slurp($test); # get rid of hashbangs as Perl::Tidy gets all huffy-like and we # disregard them anyway. $test_code =~ s/\A#![^\n]+//gm; # Strip __END__ and __DATA__ if there's nothing after it. # XXX leaving this out for now as I'm unsure if it's worth it. #$test_code =~ s/\n__(?:DATA|END)__\n$//s; if ( $test_code =~ /^(__(?:DATA|END)__)/m ) { Test::More::BAIL_OUT("Test $test not allowed to have $1 token (Test::Aggregate::Nested supports them)"); } my $package = $self->_get_package($test); push @{ $self->{_packages} } => [ $test, $package ]; if ( $setup ) { $code .= " $setup->('$test');\n"; } $code .= qq{ run_this_test_program( $package => '$test', $current_test, $total_tests, $verbose );}; if ( $teardown ) { $code .= " $teardown->('$test');\n"; } $code .= "\n"; my $set_filenames = $self->_set_filenames ? "local \$0 = '$test';" : ''; $test_packages .= <<" END_CODE"; { $separator beginning of $test $separator package $package; sub run_the_tests { $set_filenames \$REINIT_FINDBIN->(); # line 1 "$test" $test_code } $separator end of $test $separator } END_CODE } if ( $shutdown ) { $code .= " $shutdown->() if __FILE__ eq '$dump';\n"; } $code .= "}\n"; $code .= $test_packages; if ( my $tidy = $self->_tidy ) { eval "use Perl::Tidy"; my $error = $@; my $dump = $self->_dump; if ( $error && $dump ) { warn "Cannot tidy dumped code: $error"; } elsif ( !$error ) { my @output; my @tidyrc = -f $tidy ? ( perltidyrc => $tidy ) : (); Perl::Tidy::perltidy( source => \$code, destination => \@output, @tidyrc, ); $code = join '' => @output; } } return $code; } sub _as_code { my ( $self, $name ) = @_; my $method = "_$name"; return ( '', '' ) if $self->_no_streamer; my $code = $self->$method || return ( '', '' ); $code = Data::Dump::Streamer::Dump($code)->Indent(0)->Out; my $sub_name = "\$TEST_AGGREGATE_\U$name"; $code =~ s/\$CODE1/$sub_name/; return ( $sub_name, <<" END_CODE" ); my $sub_name; { $code } END_CODE } sub _slurp { my ( $class, $file ) = @_; local *FH; open FH, "< $file" or die "Cannot read ($file): $!"; return do { local $/; }; } sub _test_builder_override { my $self = shift; my $disable_test_nowarnings = ''; if ( !$self->_test_nowarnings ) { $disable_test_nowarnings = <<' END_CODE'; # Look ma, no import! BEGIN { require Test::NoWarnings; no warnings 'redefine'; *Test::NoWarnings::had_no_warnings = sub { }; *Test::NoWarnings::import = sub { my $callpack = caller(); my $ta_builder = $BUILDER->{'Test::Aggregate::Builder'}; if ( $ta_builder->{plan_for}{$callpack} ) { $ta_builder->{plan_for}{$callpack}--; } $ta_builder->{test_nowarnings_loaded}{$callpack} = 1; }; } END_CODE } return <<" END_CODE"; use Test::Aggregate; use Test::Aggregate::Builder; my \$BUILDER; BEGIN { \$BUILDER = Test::Builder->new; }; $disable_test_nowarnings; END_CODE } =head1 SETUP/TEARDOWN Since C and C blocks are for the entire aggregated tests and not for each test program (see C), you might find that you need to have setup/teardown functions for tests. These are useful if you need to setup connections to test databases, clear out temp files, or any of a variety of tasks that your test suite might require. Here's a somewhat useless example, pulled from our tests: #!/usr/bin/perl use strict; use warnings; use lib 'lib', 't/lib'; use Test::Aggregate; use Test::More; my $dump = 'dump.t'; my ( $startup, $shutdown ) = ( 0, 0 ); my ( $setup, $teardown ) = ( 0, 0 ); my $tests = Test::Aggregate->new( { dirs => 'aggtests', dump => $dump, startup => sub { $startup++ }, shutdown => sub { $shutdown++ }, setup => sub { $setup++ }, teardown => sub { $teardown++ }, } ); $tests->run; is $startup, 1, 'Startup should be called once'; is $shutdown, 1, '... as should shutdown'; is $setup, 4, 'Setup should be called once for each test program'; is $teardown, 4, '... as should teardown'; Note that you can still dump these to a dump file. This will only work if C 1.11 or later is installed. There are four attributes which can be passed to the constructor, each of which expects a code reference: =over 4 =item * C startup => \&connect_to_database, This function will be called before any of the tests are run. It is not run in a BEGIN block. =item * C shutdown => \&clean_up_temp_files, This function will be called after all of the tests are run. It will not be called in an END block. =item * C setup => sub { my $filename = shift; # this gets run before each test program. }, The setup function will be run before every test program. The name of the test file will be passed as the first argument. =item * C teardown => sub { my $filename = shift; # this gets run after every test program. } The teardown function gets run after every test program. The name of the test file will be passed as the first argument. =back =head1 GLOBAL VARIABLES You shouldn't be using global variables and a dependence on them can break your code. However, Perl provides quite a few handy global variables which, unfortunately, can easily break your tests if you change them in one test and another assumes an unchanged value. As a result, we localize many of Perl's most common global variables for you, using the following syntax: local %ENV = %ENV; The following global variables are localized for you. Any others must be localized manually per test. =over 4 =item * C<@INC> =item * C<%ENV> =item * C<%SIG> =item * C<$/> =item * C<$_> =item * C<$|> =back =head1 CAVEATS Not all tests can be included with this technique. If you have C tests, there is no need to run them with this. Otherwise: =over 4 =item * C Don't call exit() in your aggregated tests. We now warn very verbosely if this is done, but we still exit on the assumption that further tests cannot run. =item * C<__END__> and C<__DATA__> tokens. These won't work and the tests will call BAIL_OUT() if these tokens are seen. However, this limitation does not apply to L. =item * C and C blocks. Since all of the tests are aggregated together, C and C blocks will be for the scope of the entire set of aggregated tests. If you need setup/teardown facilities, see L. =item * Syntax errors Any syntax errors encountered will cause this program to BAIL_OUT(). This is why it's recommended that you move your tests into your new directory one at a time: it makes it easier to figure out which one has caused the problem. =item * C Unfortunately, due to how this works, the plan is always C. L for more information. =item * C Great module. It loves to break aggregated tests since some might have warnings when others will not. You can disable it like this: my $tests = Test::Aggregate->new( dirs => 'aggtests/', startup => sub { $INC{'Test/NoWarnings.pm'} = 1 }, ); As an alternative, you can also disable it with: my $tests = Test::Aggregate->new({ dirs => 'aggtests', test_nowarnings => 0, }); We do work internally to subtract the extra test added by C. It's painful and experimental. Good luck. =item * C Because each test is wrapped in a method call, any of your subs which access a variable in an outer scope will likely throw the above warning. Pass in arguments explicitly to suppress this. Instead of: my $x = 17; sub foo { my $y = shift; return $y + $x; } Write this: my $x = 17; sub foo { my ( $y, $x ) = @_; return $y + $x; } However, consider L. This warning does not apply with that module. =item * Singletons Be very careful of code which loads singletons. Oftimes those singletons in test suites may be altered for testing purposes, but later attempts to use those singletons can fail dramatically as they're not expecting the alterations. (Your author has painfully learned this lesson with database connections). =back =head1 DEBUGGING AGGREGATE TESTS Before aggregating tests, make sure that you add tests B to the aggregated test directory. Attempting to add many tests to the directory at once and then experiencing a failure means it will be much harder to track down which tests caused the failure. Debugging aggregated tests which fail is a multi-step process. Let's say the following fails: my $tests = Test::Aggregate->new( { dump => 'dump.t', shuffle => 1, dirs => 'aggtests', } ); $tests->run; =head2 Manually run the tests The first step is to manually run all of the tests in the C dir. prove -r aggtests/ If the failures appear the same, fix them just like you would fix any other test failure and then rerun the C code. Sometimes this means that a different number of tests run from what the aggregted tests run. Look for code which ends the program prematurely, such as an exception or an C statement. =head2 Run a dump file If this does not fix your problem, create a dump file by passing C<< dump => $dumpfile >> to the constructor (as in the above example). Then try running this dumpfile directly to attempt to replicate the error: prove -r $dumpfile =head2 Tweaking the dump file Assuming the error has been replicated, open up the dump file. The beginning of the dump file will have some code which overrides some C internals. After that, you'll see the code which runs the tests. It will look similar to this: if ( __FILE__ eq 'dump.t' ) { Test::More::diag("******** running tests for aggtests/boilerplate.t ********") if $ENV{TEST_VERBOSE}; aggtestsboilerplatet->run_the_tests; Test::More::diag("******** running tests for aggtests/subs.t ********") if $ENV{TEST_VERBOSE}; aggtestssubst->run_the_tests; Test::More::diag("******** running tests for aggtests/00-load.t ********") if $ENV{TEST_VERBOSE}; aggtests00loadt->run_the_tests; Test::More::diag("******** running tests for aggtests/slow_load.t ********") if $ENV{TEST_VERBOSE}; aggtestsslow_loadt->run_the_tests; } You can try to narrow down the problem by commenting out all of the C lines and gradually reintroducing them until you can figure out which one is actually causing the failure. =head1 COMMON PITFALLS =head2 My Tests Threw an Exception But Passed Anyway! This really isn't a C problem so much as a general Perl problem. For each test file, C wraps the tests in an eval and checks C<< my $error = $@ >>. Unfortunately, we sometimes get code like this: $server->ip_address('apple'); And internally, the 'Server' class throws an exception but uses its own evals in a C block (or something similar) to trap it. If the code you call uses an eval but fails to localize it, it wipes out I eval. Neat, eh? Thus, you never get a chance to see the error. For various reasons, this tends to impact C when a C block is triggered and calls code which internally uses eval (e.g., C). You can often fix this with: DESTROY { local $@ = $@; # localize but preserve the value my $self = shift; # do whatever you want } =head2 C and C blocks Remember that since the tests are now being run at once, these blocks will no longer run on a per-test basis, but will run for the entire aggregated set of tests. You may need to examine these individually to determine the problem. =head2 C and C blocks. Sorry, but you can't use these (just as in modperl). See L for more information about them and why they won't work. =head2 C This is a great test module. When aggregating tests together, however, it can cause pain as you'll often discover warnings that you never new existed. For a quick fix, add this before you attempt to run your tests: $INC{'Test/NoWarnings.pm'} = 1; That will disable C, but you'll want to go in later to fix them. =head2 Paths Many tests make assumptions about the paths to files and moving them into a new test directory can break this. =head2 C<$0> Tests which use C<$0> can be problematic as the code is run in an C through C and C<$0> may not match expectations. This also means that it can behave differently if run directly from a dump file. As it turns out, you can assign to C<$0>! We do this by default and set the C<$0> to the correct filename. If you don't want this behavior, pass C<< set_filenames => 0 >> to the constructor. =head2 Minimal test case If you cannot solve the problem, feel free to try and create a minimal test case and send it to me (assuming it's something I can run). =head1 AUTHOR Curtis Poe, C<< >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc Test::Aggregate You can also find information oneline: L =head1 ACKNOWLEDGEMENTS Many thanks to mauzo (L for helping me find the 'skip_all' bug. Thanks to Johan Lindström for pointing me to Apache::Registry. =head1 COPYRIGHT & LICENSE Copyright 2007 Curtis "Ovid" Poe, all rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Test-Aggregate-0.372/lib/Test/Aggregate000755001750001750 012453336671 17306 5ustar00randorando000000000000Test-Aggregate-0.372/lib/Test/Aggregate/Base.pm000444001750001750 1442712453336671 20703 0ustar00randorando000000000000package Test::Aggregate::Base; use strict; use warnings; use Carp 'croak'; use Test::Builder::Module; use Test::More; use File::Find; use vars qw(@ISA @EXPORT @EXPORT_OK); @ISA = qw(Test::Builder::Module); our $VERSION = '0.372'; $VERSION = eval $VERSION; our $_pid = $$; BEGIN { $ENV{TEST_AGGREGATE} = 1; *CORE::GLOBAL::exit = sub { my ($package, $filename, $line) = caller; # Warn about exit being called unless there's been a fork() # (in which case some form of exit is expected). if( $_pid == $$ ){ print STDERR <<" END_EXIT_WARNING"; ******** WARNING! exit called under Test::Aggregate at: File: $filename Package: $package Line: $line WARNING! ******** END_EXIT_WARNING } exit(@_); }; }; END { # for VMS delete $ENV{TEST_AGGREGATE}; } sub _code_attributes { qw/ setup teardown startup shutdown /; } sub new { my ( $class, $arg_for ) = @_; unless ( exists $arg_for->{dirs} || exists $arg_for->{tests} ) { Test::More::BAIL_OUT("You must supply 'dirs' or 'tests'"); } if ( exists $arg_for->{tests} && 'ARRAY' ne ref $arg_for->{tests} ) { Test::More::BAIL_OUT( "Argument for Test::Aggregate 'tests' key must be an array reference" ); } $arg_for->{test_nowarnings} = 1 unless exists $arg_for->{test_nowarnings}; $arg_for->{set_filenames} = 1 unless exists $arg_for->{set_filenames}; $arg_for->{findbin} = 1 unless exists $arg_for->{findbin}; my $dirs = delete $arg_for->{dirs}; if ( defined $dirs ) { $dirs = [$dirs] if 'ARRAY' ne ref $dirs; } else { $dirs = []; } my $matching = qr//; if ( $arg_for->{matching} ) { $matching = delete $arg_for->{matching}; unless ( 'Regexp' eq ref $matching ) { croak("Argument for 'matching' must be a pre-compiled regex"); } } my $has_code_attributes; foreach my $attribute ( $class->_code_attributes ) { if ( my $ref = $arg_for->{$attribute} ) { if ( 'CODE' ne ref $ref ) { croak("Attribute ($attribute) must be a code reference"); } else { $has_code_attributes++; } } } my $self = bless { dirs => $dirs, matching => $matching, _no_streamer => 0, _packages => [], aggregate_program => $0, } => $class; if ( delete $arg_for->{check_plan} ) { Carp::carp("'check_plan' is now deprecated and a no-op."); } $self->{$_} = delete $arg_for->{$_} foreach ( qw/ dry dump findbin no_generate_plan set_filenames shuffle test_nowarnings tests tidy verbose /, $class->_code_attributes ); $self->{tests} ||= []; if ( my @keys = keys %$arg_for ) { local $" = ', '; croak("Unknown keys to &new: (@keys)"); } if ($has_code_attributes) { eval "use Data::Dump::Streamer"; if ( my $error = $@ ) { $self->{_no_streamer} = 1; if ( my $dump = $self->_dump ) { warn <<" END_WARNING"; Dump file ($dump) cannot be generated. A code attributes was requested but we cannot load Data::Dump::Streamer: $error. END_WARNING $self->{dump} = ''; } } } return $self; } # set from user data sub _dump { shift->{dump} || '' } sub _dry { shift->{dry} } sub _should_shuffle { shift->{shuffle} } sub _matching { shift->{matching} } sub _set_filenames { shift->{set_filenames} } sub _findbin { shift->{findbin} } sub _dirs { @{ shift->{dirs} } } sub _startup { shift->{startup} } sub _shutdown { shift->{shutdown} } sub _setup { shift->{setup} } sub _teardown { shift->{teardown} } sub _tests { @{ shift->{tests} } } sub _tidy { shift->{tidy} } sub _test_nowarnings { shift->{test_nowarnings} } sub _verbose { my $self = shift; $self->{verbose} ? $self->{verbose} : 0; } # set from internal data sub _no_streamer { shift->{_no_streamer} } sub _packages { @{ shift->{_packages} } } sub _get_tests { my $self = shift; my @tests; my $matching = $self->_matching; if ( $self->_dirs ) { find( { no_chdir => 1, wanted => sub { push @tests => $File::Find::name if /\.t\z/ && /$matching/; } }, $self->_dirs ); } push @tests => $self->_tests; if ( $self->_should_shuffle ) { $self->_shuffle(@tests); } else { @tests = sort @tests; } return @tests; } sub _shuffle { my $self = shift; # Fisher-Yates shuffle my $i = @_; while ($i) { my $j = rand $i--; @_[ $i, $j ] = @_[ $j, $i ]; } return; } sub _get_package { my ( $class, $file ) = @_; $file =~ s/\W//g; return $file; } 1; __END__ =encoding utf-8 =head1 NAME Test::Aggregate::Base - Base class for aggregated tests. =head1 VERSION Version 0.372 =head1 SYNOPSIS use base 'Test::Aggregate::base'; sub run { ... } =head1 DESCRIPTION This module is for internal use only. =head1 AUTHOR Curtis Poe, C<< >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc Test::Aggregate::Base You can also find information oneline: L =head1 ACKNOWLEDGEMENTS Many thanks to mauzo (L for helping me find the 'skip_all' bug. Thanks to Johan Lindström for pointing me to Apache::Registry. =head1 COPYRIGHT & LICENSE Copyright 2007 Curtis "Ovid" Poe, all rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut Test-Aggregate-0.372/lib/Test/Aggregate/Builder.pm000444001750001750 1537312453336671 21420 0ustar00randorando000000000000package Test::Aggregate::Builder; use strict; use warnings; =encoding utf-8 =head1 NAME Test::Aggregate::Builder - Internal overrides for Test::Builder. =head1 VERSION Version 0.372 =cut our $VERSION = '0.372'; $VERSION = eval $VERSION; =head1 SYNOPSIS use Test::Aggregate::Builder; =head1 DESCRIPTION B: This module is for internal use only. DO NOT USE DIRECTLY. =cut BEGIN { $ENV{TEST_AGGREGATE} = 1 } END { # for VMS delete $ENV{TEST_AGGREGATE}; } use Test::Builder; { my $DONE_TESTING; BEGIN { no warnings 'redefine'; if ( Test::Builder->can('done_testing') ) { $DONE_TESTING = \&Test::Builder::done_testing; *Test::Builder::done_testing = sub { my ( $self, $num_tests ) = @_; $self->expected_tests( defined $num_tests ? $num_tests : $self->current_test ); return; }; my $output_plan = \&Test::Builder::_output_plan; *Test::Builder::_output_plan = sub { return unless $_[0]->{Done_Testing}; goto $output_plan; }; } else { *Test::Builder::_plan_check = sub { my $self = shift; # Will this break under threads? $self->{Expected_Tests} = $self->{Curr_Test} + 1; }; } } END { my $tb = Test::Builder->new; $tb->{'Test::Aggregate::Builder'}{ignore_timing_blocks} = 1; my $tests = $tb->current_test; $tb->expected_tests($tests); if ( $DONE_TESTING ) { $tb->$DONE_TESTING($tests); } else { $tb->_print("1..$tests\n") unless $tb->{Have_Output_Plan}; } } } no warnings 'redefine'; # The following is done to get around the fact that deferred plans are not # supported. Unfortunately, there's no clean way to override this, but this # allows us to minimize the monkey patching. # XXX We fully-qualify the sub names because PAUSE won't index what it thinks # is an attempt to hijack the Test::Builder namespace. sub Test::Builder::no_header { 1 } { # prevent the 'you tried to plan twice' errors my $plan; BEGIN { $plan = \&Test::Builder::plan } our $skip = \1; sub Test::Builder::plan { delete $_[0]->{Have_Plan}; $_[0]->{'Test::Aggregate::Builder'} ||= {}; my $tab_builder = $_[0]->{'Test::Aggregate::Builder'}; if ( 'skip_all' eq ( $_[1] || '' ) ) { my $callpack = caller(1); $tab_builder->{skip_all}{$callpack} = $_[2]; my $running_test = $tab_builder->{running}; die $skip if defined $running_test && $running_test eq $callpack; return; } my $callpack = caller(1); if ( 'tests' eq ( $_[1] || '' ) ) { $tab_builder->{plan_for}{$callpack} = $_[2]; if ( $tab_builder->{test_nowarnings_loaded}{$callpack} ) { # Test::NoWarnings was loaded before plan() was called, so it # didn't have a change to decrement it $tab_builder->{plan_for}{$callpack}--; } } $plan->(@_); } } { my $ok; BEGIN { $ok = \&Test::Builder::ok } my %FORBIDDEN = map { $_ => 1 } qw/BEGIN CHECK INIT END/; sub Test::Builder::ok { __check_test_count(@_); my $level = 1; while (1) { my ($caller) = ( ( ( caller($level) )[3] || '' ) =~ /::([[:word:]]+)\z/ ); last unless $caller; if ( $FORBIDDEN{$caller} && not $_[0] ->{'Test::Aggregate::Builder'}{ignore_timing_blocks} ) { my ( $self, $test, $name ) = @_; $test = $test ? "Yes" : "No"; my ( $filename, $line ) = ( caller($level) )[ 1, 2 ]; $self->diag(<<" END"); >>>> DEPRECATION WARNING <<<< >>>> See http://use.perl.org/~Ovid/journal/38974 <<<< Aggregated tests should not be run in BEGIN, CHECK, INIT or END blocks. File: $filename Line: $line Name: $name Pass: $test END } $level++; } local $Test::Builder::Level = $Test::Builder::Level + 1; $ok->(@_); } } { my $reset; BEGIN { $reset = \&Test::Builder::reset } sub Test::Builder::reset { my $self = shift; $reset->($self); $self->{'Test::Aggregate::Builder'} = { plan_for => {}, tests_run => {}, file_for => {}, test_nowarnings_loaded => {}, skip_all => {}, check_plan => undef, last_test => undef, }; } } { # Called in _ending and prevents the 'you tried to run a test without a # plan' error. my $_sanity_check; BEGIN { $_sanity_check = \&Test::Builder::_sanity_check } sub Test::Builder::_sanity_check { $_[0]->{Have_Plan} = 1; $_sanity_check->(@_); } } { my $skip; BEGIN { $skip = \&Test::Builder::skip } sub Test::Builder::skip { __check_test_count(@_); $skip->(@_); } } # two purposes: we check the test cout for a package, but we also return the # package name sub __check_test_count { my $self = shift; my $callpack; return unless $self->{'Test::Aggregate::Builder'}{check_plan}; my $stack_level = 1; while ( my ( $package, undef, undef, $subroutine ) = caller($stack_level) ) { last if 'Test::Aggregate' eq $package; # XXX Because these blocks aren't really subroutines, caller() # doesn't report what you expect. last if $callpack && $subroutine =~ /::(?:BEGIN|END)\z/; $callpack = $package; $stack_level++; } { no warnings 'uninitialized'; $self->{'Test::Aggregate::Builder'}{tests_run}{$callpack} += 1; } return $callpack; } =head1 AUTHOR Curtis Poe, C<< >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc Test::Aggregate::Builder You can also find information oneline: L =head1 COPYRIGHT & LICENSE Copyright 2007 Curtis "Ovid" Poe, all rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut 1; Test-Aggregate-0.372/lib/Test/Aggregate/Nested.pm000444001750001750 2022212453336671 21241 0ustar00randorando000000000000package Test::Aggregate::Nested; use strict; use warnings; use Test::More; use Test::Aggregate::Base; use Carp; use FindBin; use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION); @ISA = 'Test::Aggregate::Base'; =encoding utf-8 =head1 NAME Test::Aggregate::Nested - Aggregate C<*.t> tests to make them run faster. =head1 VERSION Version 0.372 =cut our $VERSION = '0.372'; $VERSION = eval $VERSION; =head1 SYNOPSIS use Test::Aggregate::Nested; my $tests = Test::Aggregate::Nested->new( { dirs => $aggregate_test_dir, verbose => 1, } ); $tests->run; =head1 DESCRIPTION B: this is alpha code. Conceptually it is superior to C, but in reality, it might not be. We'll see. This module is almost identical to C and will in the future be the preferred way of aggregating tests (until someone comes up with something better :) C requires a 0.8901 or better of C. This is because we use its C function. Currently we C if this function is not available. Because the TAP output is nested, you'll find it much easier to see which tests result in which output. For example, consider the following snippet of TAP. 1..2 1..5 ok 1 - aggtests/check_plan.t ***** 1 ok 2 - aggtests/check_plan.t ***** 2 ok 3 # skip checking plan (aggtests/check_plan.t ***** 3) ok 4 - env variables should not hang around ok 5 - aggtests/check_plan.t ***** 4 ok 1 - Tests for aggtests/check_plan.t 1..1 ok 1 - subs work! ok 2 - Tests for aggtests/subs.t At the end of each nested test is a summary test line explaining which program we ran tests for. C asserts a plan equal to the number of test files aggregated, something which C could not do. Because of this, we no longer export C functions. If you need additional tests before or after aggregation, you can run the aggregated tests in a subtest: use Test::More tests => 2; use Test::Aggregate::Nested; subtest 'Nested tests' => sub { Test::Aggregate::Nested->new({ dirs => 'aggtests/' })->run; }; ok $some_other_test; or disable the generation of the plan with the parameter C: use Test::More; use Test::Aggregate::Nested; Test::Aggregate::Nested->new({ dirs => 'aggtests/', no_generate_plan => 1 })->run; ok $some_other_test; done_testing(); =head1 CAVEATS C is much cleaner than C, so I don't support the C argument. If this is needed, let me know and I'll see about fixing this. The "variable will not stay shared" warnings from C (see its CAVEATS section) are no longer applicable. =cut my $REINIT_FINDBIN = FindBin->can(q/again/) || sub {}; sub new { my ( $class, $arg_for ) = @_; if ( $arg_for->{dump} ) { require Carp; carp("Dump files are not supported under Test::Aggregate::Nested."); } unless ( Test::More->can('subtest') ) { my $tm_version = Test::More->VERSION; croak(<<" END"); Test::More version $tm_version does not support nested TAP. Please upgrade to version 0.8901 or newer to use Test::Aggregate::Nested. END } $class->SUPER::new($arg_for); } sub run { my $self = shift; local $Test::Aggregate::Base::_pid = $$; my %test_phase; foreach my $attr ( $self->_code_attributes ) { my $method = "_$attr"; $test_phase{$attr} = $self->$method || sub { }; } my @tests = $self->_get_tests; my ( $current, $total ) = ( 0, scalar @tests ); if (! $self->{no_generate_plan}) { plan tests => $total; } $test_phase{startup}->(); for my $test (@tests) { $current++; no warnings 'uninitialized'; local %ENV = %ENV; local $/ = $/; local @INC = @INC; local $_ = $_; local $| = $|; local %SIG = %SIG; local $@; use warnings 'uninitialized'; # restrict this scope as much as possible local $0 = $test; $test_phase{setup}->($test); $REINIT_FINDBIN->() if $self->_findbin; my $package = $self->_get_package($test); if ( $self->_verbose ) { Test::More::diag("Running tests for $test ($current out of $total)"); } eval <<" END"; package $package; Test::Aggregate::Nested::_do_file_as_subtest(\$test); END diag $@ if $@; $test_phase{teardown}->($test); } $test_phase{shutdown}->(); } sub run_this_test_program { } sub _do_file_as_subtest { my ($test) = @_; subtest("Tests for $test", sub { my $error; my $diag; { local ($@, $!); # if do("file") fails it will return undef (and set $@ or $!) unless(defined( my $return = do $test )){ # If there was an error be sure to propogate it. # This isn't quite the same as what's described by `perldoc -f do` # because there are no rules about what a .t file should return. # If the file doesn't return a defined value there's no way to # tell the difference between a test that errored and one that # returned undef but did something that happened to set `$!` # (for example, a file that skips when it looks for a file that # isn't found), so we shouldn't treat it as an error. # If the file fails to read then subtest() will complain # that no tests were run (and consider it a failure). # That should be sufficient. my $ex_class = 'Test::Builder::Exception'; if( my $e = $@ ){ $error = "Couldn't parse '$test': $e" unless ( # a skip in a subtest will be an object ref($e) ? eval { $e->isa($ex_class) } : # a skip in a BEGIN ("use Test::More skip_all => $message") gets stringified $e =~ /^\Q${ex_class}=HASH(0x\E[[:xdigit:]]+\Q)BEGIN failed--compilation aborted\E/ ); } # If tests have been run we can assume the file was read. # If not, print a warning message. # Either way Test::Builder will handle marking it as pass/fail. elsif( scalar(Test::Builder->new->details) == 0 ){ # It might have been an error, or might not, so try to get # the author to help us out. $diag = < >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc Test::Aggregate::Nested You can also find information oneline: L =head1 ACKNOWLEDGEMENTS Many thanks to mauzo (L for helping me find the 'skip_all' bug. Thanks to Johan Lindström for pointing me to Apache::Registry. =head1 COPYRIGHT & LICENSE Copyright 2007 Curtis "Ovid" Poe, all rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut Test-Aggregate-0.372/aggtests-nested000755001750001750 012453336671 17034 5ustar00randorando000000000000Test-Aggregate-0.372/aggtests-nested/number_of_tests.t000444001750001750 52312453336671 22534 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use Test::More tests => 4; sub num_tests { return scalar(Test::Builder->new->details); } is num_tests(), 0, 'no tests yet'; is num_tests(), 1, 'that check created a test'; SKIP: { skip "it's my party and i'll skip if i want to", 1; ok 1; } is num_tests(), 3, 'skip adds a detail'; Test-Aggregate-0.372/aggtests-nested/data_handle.t000444001750001750 24112453336671 21557 0ustar00randorando000000000000#!/usr/bin/perl use strict; use warnings; use Test::More tests => 1; is scalar(), "aggregation!\n", 'data handle is accessible'; __DATA__ aggregation!