File Coverage

blib/lib/Test2/Tools/Spec.pm
Criterion Covered Total %
statement 225 337 66.7
branch 60 178 33.7
condition 19 71 26.7
subroutine 30 37 81.0
pod 17 21 80.9
total 351 644 54.5


line stmt bran cond sub pod time code
1             package Test2::Tools::Spec;
2 43     43   4360171 use strict;
  43         90  
  43         1000  
3 43     43   145 use warnings;
  43         69  
  43         982  
4              
5 43     43   149 use Carp qw/croak/;
  43         80  
  43         1871  
6 43     43   14213 use Test2::Workflow qw/parse_args build current_build root_build init_root build_stack/;
  43         67  
  43         2797  
7              
8 43     43   18018 use Test2::Workflow::Runner();
  43         106  
  43         1081  
9 43     43   225 use Test2::Workflow::Task::Action();
  43         56  
  43         529  
10 43     43   143 use Test2::Workflow::Task::Group();
  43         52  
  43         517  
11 43     43   137 use Test2::Tools::Mock();
  43         55  
  43         452  
12 43     43   140 use Importer();
  43         68  
  43         643  
13              
14 43     43   339 use vars qw/@EXPORT @EXPORT_OK/;
  43         52  
  43         22338  
15             push @EXPORT => qw{describe cases};
16             push @EXPORT_OK => qw{include_workflow include_workflows spec_defaults};
17              
18             my %HANDLED;
19             sub import {
20 42     42   397 my $class = shift;
21 42         297 my @caller = caller(0);
22              
23 42         85 my %root_args;
24             my %runner_args;
25 0         0 my @import;
26 42         171 while (my $arg = shift @_) {
27 39 100       155 if ($arg =~ s/^-//) {
28 12         19 my $val = shift @_;
29              
30 12 50       149 if (Test2::Workflow::Runner->can($arg)) {
    0          
    0          
    0          
31 12         53 $runner_args{$arg} = $val;
32             }
33             elsif (Test2::Workflow::Task::Group->can($arg)) {
34 0         0 $root_args{$arg} = $val;
35             }
36             elsif ($arg eq 'root_args') {
37 0         0 %root_args = (%root_args, %$val);
38             }
39             elsif ($arg eq 'runner_args') {
40 0         0 %runner_args = (%runner_args, %$val);
41             }
42             else {
43 0         0 croak "Unrecognized arg: $arg";
44             }
45             }
46             else {
47 27         63 push @import => $arg;
48             }
49             }
50              
51 42 50       155 if ($HANDLED{$caller[0]}++) {
52 0 0 0     0 croak "Package $caller[0] has already been initialized"
53             if keys(%root_args) || keys(%runner_args);
54             }
55             else {
56             my $root = init_root(
57             $caller[0],
58             frame => \@caller,
59 0     0   0 code => sub { 1 },
60 42         368 %root_args,
61             );
62              
63 42         164 my $runner = Test2::Workflow::Runner->new(%runner_args);
64              
65             Test2::Tools::Mock->add_handler(
66             $caller[0],
67             sub {
68 12     12   17251 my %params = @_;
69 12         45 my ($class, $caller, $builder, $args) = @params{qw/class caller builder args/};
70              
71 12         906 my $do_it = eval "package $caller->[0];\n#line $caller->[2] \"$caller->[1]\"\nsub { \$runner\->add_mock(\$builder->()) }";
72              
73             # Running
74 12 100       118 if (@{$runner->stack}) {
  12         72  
75 6         28 $do_it->();
76             }
77             else { # Not running
78 6         132 my $action = Test2::Workflow::Task::Action->new(
79             code => $do_it,
80             name => "mock $class",
81             frame => $caller,
82             scaffold => 1,
83             );
84              
85 6   33     42 my $build = current_build() || $root;
86              
87 6         35 $build->add_primary_setup($action);
88 6 50       61 $build->add_stash($builder->()) unless $build->is_root;
89             }
90              
91 12         64 return 1;
92             }
93 42         721 );
94              
95 42         553 my $stack = Test2::API::test2_stack;
96 42         453 $stack->top; # Insure we have a hub
97 42         1541630 my ($hub) = Test2::API::test2_stack->all;
98 42         591 $hub->set_active(1);
99             $hub->follow_up(
100             sub {
101 38 100   38   272024 return unless $root->populated;
102 36         156 my $g = $root->compile;
103 36         339 $runner->push_task($g);
104 36         285 $runner->run;
105             }
106 42         495 );
107             }
108              
109 42         821 Importer->import_into($class, $caller[0], @import);
110             }
111              
112             {
113 43     43   237 no warnings 'once';
  43         1236  
  43         25900  
114             *cases = \&describe;
115             *include_workflows = \&include_workflow;
116             }
117              
118             sub describe {
119 91     91 0 4995 my @caller = caller(0);
120              
121 91         148 my $want = wantarray;
122              
123 91 100       510 my $build = build(args => \@_, caller => \@caller, stack_stop => defined $want ? 1 : 0);
124              
125 86 100       243 return $build if defined $want;
126              
127 54 50 66     176 my $current = current_build() || root_build($caller[0])
128             or croak "No current workflow build!";
129              
130 54         133 $current->add_primary($build);
131             }
132              
133             sub include_workflow {
134 5     5 0 65 my @caller = caller(0);
135              
136 5 50 33     15 my $build = current_build() || root_build(\$caller[0])
137             or croak "No current workflow build!";
138              
139 5         15 for my $task (@_) {
140 5 50       30 croak "include_workflow only accepts Test2::Workflow::Task objects, got: $task"
141             unless $task->isa('Test2::Workflow::Task');
142              
143 5         35 $build->add_primary($task);
144             }
145             }
146              
147             sub defaults {
148 642     642 0 1073 my %params = @_;
149              
150 642         821 my ($package, $tool) = @params{qw/package tool/};
151              
152 642         1054 my @stack = (root_build($package), build_stack());
153 642 50       969 return unless @stack;
154              
155 642         502 my %out;
156 642         741 for my $build (@stack) {
157 1313 100       3002 %out = () if $build->stack_stop;
158 1313 100       4041 my $new = $build->defaults->{$tool} or next;
159 63         351 %out = (%out, %$new);
160             }
161              
162 642         2774 return \%out;
163             }
164              
165              
166             # Generate a bunch of subs that only have minor differences between them.
167             BEGIN {
168 43     43   169 @EXPORT = qw{
169             tests it
170             case
171             before_all around_all after_all
172             before_case around_case after_case
173             before_each around_each after_each
174             };
175              
176 43         82 @EXPORT_OK = qw{
177             mini
178             iso miso
179             async masync
180             };
181              
182 43         717 my %stages = (
183             case => ['add_variant'],
184             tests => ['add_primary'],
185             it => ['add_primary'],
186              
187             iso => ['add_primary'],
188             miso => ['add_primary'],
189              
190             async => ['add_primary'],
191             masync => ['add_primary'],
192              
193             mini => ['add_primary'],
194              
195             before_all => ['add_setup'],
196             after_all => ['add_teardown'],
197             around_all => ['add_setup', 'add_teardown'],
198              
199             before_case => ['add_variant_setup'],
200             after_case => ['add_variant_teardown'],
201             around_case => ['add_variant_setup', 'add_variant_teardown'],
202              
203             before_each => ['add_primary_setup'],
204             after_each => ['add_primary_teardown'],
205             around_each => ['add_primary_setup', 'add_primary_teardown'],
206             );
207              
208 43         613 my %props = (
209             case => [],
210             tests => [],
211             it => [],
212              
213             iso => [iso => 1],
214             miso => [iso => 1, flat => 1],
215              
216             async => [async => 1],
217             masync => [async => 1, flat => 1],
218              
219             mini => [flat => 1],
220              
221             before_all => [scaffold => 1],
222             after_all => [scaffold => 1],
223             around_all => [scaffold => 1, around => 1],
224              
225             before_case => [scaffold => 1],
226             after_case => [scaffold => 1],
227             around_case => [scaffold => 1, around => 1],
228              
229             before_each => [scaffold => 1],
230             after_each => [scaffold => 1],
231             around_each => [scaffold => 1, around => 1],
232             );
233              
234             sub spec_defaults {
235 18     18 0 684 my ($tool, %params) = @_;
236 18         108 my @caller = caller(0);
237              
238             croak "'$tool' is not a spec tool"
239 18 0 33     54 unless exists $props{$tool} || exists $stages{$tool};
240              
241 18 50 33     54 my $build = current_build() || root_build($caller[0])
242             or croak "No current workflow build!";
243              
244 18   50     63 my $old = $build->defaults->{$tool} ||= {};
245 18         153 $build->defaults->{$tool} = { %$old, %params };
246             }
247              
248 43         90 my $run = "";
249 43         87 for my $func (@EXPORT, @EXPORT_OK) {
250 731         524 $run .= <<" EOT";
251 731         826 #line ${ \(__LINE__ + 1) } "${ \__FILE__ }"
  731         2275  
252             sub $func {
253 27     27 1 234 my \@caller = caller(0);
  9     9 1 99  
  36     36 1 289  
  27     27 1 234  
  9     9 1 72  
  28     28 1 734  
  0     0 1 0  
  28     28 1 277  
  9     9 1 81  
  37     37 1 342  
  78     78 1 709  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  355     355 1 9028  
254 27         81 my \$args = parse_args(args => \\\@_, caller => \\\@caller);
  9         36  
  36         102  
  27         84  
  9         27  
  28         79  
  0         0  
  28         100  
  9         27  
  37         99  
  78         235  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  355         994  
255 27         34 my \$action = Test2::Workflow::Task::Action->new(\@{\$props{$func}}, %\$args);
  27         106  
  9         18  
  9         36  
  36         44  
  36         128  
  27         36  
  27         106  
  9         9  
  9         477  
  28         41  
  28         105  
  0         0  
  0         0  
  28         40  
  28         214  
  9         18  
  9         45  
  37         49  
  37         159  
  78         99  
  78         310  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  355         375  
  355         1591  
256              
257 27 50       396 return \$action if defined wantarray;
  9 50       45  
  36 50       137  
  27 50       108  
  9 50       54  
  28 50       123  
  0 0       0  
  28 50       102  
  9 50       36  
  37 50       186  
  78 50       288  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  355 100       1267  
258              
259 27 50 33     57 my \$build = current_build() || root_build(\$caller[0])
  9 50 33     18  
  36 50 33     76  
  27 50 33     59  
  9 50 33     18  
  28 50 33     55  
  0 0 0     0  
  28 50 33     70  
  9 50 33     18  
  37 50 33     63  
  78 50 33     137  
  0 0 0     0  
  0 0 0     0  
  0 0 0     0  
  0 0 0     0  
  0 0 0     0  
  354 50 66     750  
260             or croak "No current workflow build!";
261              
262 27 50       56 if (my \$defaults = defaults(package => \$caller[0], tool => '$func')) {
  9 50       27  
  36 50       91  
  27 50       55  
  9 50       27  
  28 50       58  
  0 0       0  
  28 50       65  
  9 50       27  
  37 50       73  
  78 50       165  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  354 50       597  
263 27         54 for my \$attr (keys \%\$defaults) {
  9         27  
  36         84  
  27         58  
  9         27  
  28         110  
  0         0  
  28         66  
  9         72  
  37         126  
  78         140  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  354         672  
264 0 0       0 next if defined \$action->\$attr;
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  36 100       90  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  72 50       180  
265 0         0 my \$sub = "set_\$attr";
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  18         72  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  72         207  
266 0         0 \$action->\$sub(\$defaults->{\$attr});
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  18         45  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  72         216  
267             }
268             }
269              
270 27         33 \$build->\$_(\$action) for \@{\$stages{$func}};
  27         112  
  9         9  
  9         45  
  36         33  
  36         168  
  27         40  
  27         87  
  9         18  
  9         45  
  28         37  
  28         97  
  0         0  
  0         0  
  28         22  
  28         146  
  9         9  
  9         45  
  37         56  
  37         144  
  78         88  
  78         278  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  354         315  
  354         1241  
271             }
272             EOT
273             }
274              
275 43         65 my ($ok, $err);
276             {
277 43         350 local $@;
  43         62  
278 43         97512 $ok = eval "$run\n1";
279 43         95 $err = $@;
280             }
281              
282 43 50       1254 die $@ unless $ok;
283             }
284              
285             1;
286              
287             __END__