1package Test2::Tools::Defer; 2use strict; 3use warnings; 4 5our $VERSION = '0.000162'; 6 7use Carp qw/croak/; 8 9use Test2::Util qw/get_tid/; 10use Test2::API qw{ 11 test2_add_callback_exit 12 test2_pid test2_tid 13}; 14 15our @EXPORT = qw/def do_def/; 16use base 'Exporter'; 17 18my %TODO; 19 20sub def { 21 my ($func, @args) = @_; 22 23 my @caller = caller(0); 24 25 $TODO{$caller[0]} ||= []; 26 push @{$TODO{$caller[0]}} => [$func, \@args, \@caller]; 27} 28 29sub do_def { 30 my $for = caller; 31 my $tests = delete $TODO{$for} or croak "No tests to run!"; 32 33 for my $test (@$tests) { 34 my ($func, $args, $caller) = @$test; 35 36 my ($pkg, $file, $line) = @$caller; 37 38 chomp(my $eval = <<" EOT"); 39package $pkg; 40# line $line "(eval in Test2::Tools::Defer) $file" 41\&$func(\@\$args); 421; 43 EOT 44 45 eval $eval and next; 46 chomp(my $error = $@); 47 48 require Data::Dumper; 49 chomp(my $td = Data::Dumper::Dumper($args)); 50 $td =~ s/^\$VAR1 =/\$args: /; 51 die <<" EOT"; 52Exception: $error 53--eval-- 54$eval 55-------- 56Tool: $func 57Caller: $caller->[0], $caller->[1], $caller->[2] 58$td 59 EOT 60 } 61 62 return; 63} 64 65sub _verify { 66 my ($context, $exit, $new_exit) = @_; 67 68 my $not_ok = 0; 69 for my $pkg (keys %TODO) { 70 my $tests = delete $TODO{$pkg}; 71 my $caller = $tests->[0]->[-1]; 72 print STDOUT "not ok - deferred tests were not run!\n" unless $not_ok++; 73 print STDERR "# '$pkg' has deferred tests that were never run!\n"; 74 print STDERR "# $caller->[1] at line $caller->[2]\n"; 75 $$new_exit ||= 255; 76 } 77} 78 79test2_add_callback_exit(\&_verify); 80 811; 82 83__END__ 84 85=pod 86 87=encoding UTF-8 88 89=head1 NAME 90 91Test2::Tools::Defer - Write tests that get executed at a later time 92 93=head1 DESCRIPTION 94 95Sometimes you need to test things BEFORE loading the necessary functions. This 96module lets you do that. You can write tests, and then have them run later, 97after C<Test2> is loaded. You tell it what test function to run, and what 98arguments to give it. The function name and arguments will be stored to be 99executed later. When ready, run C<do_def()> to kick them off once the functions 100are defined. 101 102=head1 SYNOPSIS 103 104 use strict; 105 use warnings; 106 107 use Test2::Tools::Defer; 108 109 BEGIN { 110 def ok => (1, 'pass'); 111 def is => ('foo', 'foo', 'runs is'); 112 ... 113 } 114 115 use Test2::Tools::Basic; 116 117 do_def(); # Run the tests 118 119 # Declare some more tests to run later: 120 def ok => (1, "another pass"); 121 ... 122 123 do_def(); # run the new tests 124 125 done_testing; 126 127=head1 EXPORTS 128 129=over 4 130 131=item def function => @args; 132 133This will store the function name, and the arguments to be run later. Note that 134each package has a separate store of tests to run. 135 136=item do_def() 137 138This will run all the stored tests. It will also reset the list to be empty so 139you can add more tests to run even later. 140 141=back 142 143=head1 SOURCE 144 145The source code repository for Test2-Suite can be found at 146F<https://github.com/Test-More/Test2-Suite/>. 147 148=head1 MAINTAINERS 149 150=over 4 151 152=item Chad Granum E<lt>exodist@cpan.orgE<gt> 153 154=back 155 156=head1 AUTHORS 157 158=over 4 159 160=item Chad Granum E<lt>exodist@cpan.orgE<gt> 161 162=back 163 164=head1 COPYRIGHT 165 166Copyright 2018 Chad Granum E<lt>exodist@cpan.orgE<gt>. 167 168This program is free software; you can redistribute it and/or 169modify it under the same terms as Perl itself. 170 171See F<http://dev.perl.org/licenses/> 172 173=cut 174