File Coverage

blib/lib/Test2/Tools/Spec.pm
Criterion Covered Total %
statement 225 336 66.9
branch 60 178 33.7
condition 19 71 26.7
subroutine 31 38 81.5
pod 17 21 80.9
total 352 644 54.6


line stmt bran cond sub pod time code
1             package Test2::Tools::Spec;
2 44     44   20380 use strict;
  44         110  
  44         1310  
3 44     44   277 use warnings;
  44         140  
  44         1723  
4              
5             our $VERSION = '0.000156';
6              
7 44     44   232 use Carp qw/croak/;
  44         77  
  44         2188  
8 44     44   18297 use Test2::Workflow qw/parse_args build current_build root_build init_root build_stack/;
  44         116  
  44         3350  
9              
10 44     44   329 use Test2::API qw/test2_add_callback_testing_done/;
  44         109  
  44         1700  
11              
12 44     44   21134 use Test2::Workflow::Runner();
  44         133  
  44         1026  
13 44     44   328 use Test2::Workflow::Task::Action();
  44         91  
  44         701  
14 44     44   231 use Test2::Workflow::Task::Group();
  44         130  
  44         788  
15 44     44   270 use Test2::Tools::Mock();
  44         102  
  44         614  
16 44     44   226 use Test2::Util::Importer();
  44         80  
  44         987  
17              
18 44     44   265 use vars qw/@EXPORT @EXPORT_OK/;
  44         118  
  44         30370  
19             push @EXPORT => qw{describe cases};
20             push @EXPORT_OK => qw{include_workflow include_workflows spec_defaults};
21              
22             my %HANDLED;
23             sub import {
24 43     43   537 my $class = shift;
25 43         356 my @caller = caller(0);
26              
27 43         178 my %root_args;
28             my %runner_args;
29 43         0 my @import;
30 43         191 while (my $arg = shift @_) {
31 39 100       190 if ($arg =~ s/^-//) {
32 12         31 my $val = shift @_;
33              
34 12 50       80 if (Test2::Workflow::Runner->can($arg)) {
    0          
    0          
    0          
35 12         58 $runner_args{$arg} = $val;
36             }
37             elsif (Test2::Workflow::Task::Group->can($arg)) {
38 0         0 $root_args{$arg} = $val;
39             }
40             elsif ($arg eq 'root_args') {
41 0         0 %root_args = (%root_args, %$val);
42             }
43             elsif ($arg eq 'runner_args') {
44 0         0 %runner_args = (%runner_args, %$val);
45             }
46             else {
47 0         0 croak "Unrecognized arg: $arg";
48             }
49             }
50             else {
51 27         90 push @import => $arg;
52             }
53             }
54              
55 43 50       370 if ($HANDLED{$caller[0]}++) {
56 0 0 0     0 croak "Package $caller[0] has already been initialized"
57             if keys(%root_args) || keys(%runner_args);
58             }
59             else {
60             my $root = init_root(
61             $caller[0],
62             frame => \@caller,
63 0     0   0 code => sub { 1 },
64 43         327 %root_args,
65             );
66              
67 43         226 my $runner = Test2::Workflow::Runner->new(%runner_args);
68              
69             Test2::Tools::Mock->add_handler(
70             $caller[0],
71             sub {
72 12     12   87 my %params = @_;
73 12         50 my ($class, $caller, $builder, $args) = @params{qw/class caller builder args/};
74              
75 12         935 my $do_it = eval "package $caller->[0];\n#line $caller->[2] \"$caller->[1]\"\nsub { \$runner\->add_mock(\$builder->()) }";
76              
77             # Running
78 12 100       148 if (@{$runner->stack}) {
  12         61  
79 6         47 $do_it->();
80             }
81             else { # Not running
82 6         122 my $action = Test2::Workflow::Task::Action->new(
83             code => $do_it,
84             name => "mock $class",
85             frame => $caller,
86             scaffold => 1,
87             );
88              
89 6   33     44 my $build = current_build() || $root;
90              
91 6         51 $build->add_primary_setup($action);
92 6 50       76 $build->add_stash($builder->()) unless $build->is_root;
93             }
94              
95 12         97 return 1;
96             }
97 43         662 );
98              
99             test2_add_callback_testing_done(
100             sub {
101 39 100   39   7518 return unless $root->populated;
102 37         354 my $g = $root->compile;
103 37         604 $runner->push_task($g);
104 37         433 $runner->run;
105             }
106 43         267 );
107             }
108              
109 43         1642 Test2::Util::Importer->import_into($class, $caller[0], @import);
110             }
111              
112             {
113 44     44   391 no warnings 'once';
  44         116  
  44         36927  
114             *cases = \&describe;
115             *include_workflows = \&include_workflow;
116             }
117              
118             sub describe {
119 92     92 0 7129 my @caller = caller(0);
120              
121 92         247 my $want = wantarray;
122              
123 92 100       788 my $build = build(args => \@_, caller => \@caller, stack_stop => defined $want ? 1 : 0);
124              
125 87 100       400 return $build if defined $want;
126              
127 55 50 66     164 my $current = current_build() || root_build($caller[0])
128             or croak "No current workflow build!";
129              
130 55         210 $current->add_primary($build);
131             }
132              
133             sub include_workflow {
134 5     5 0 85 my @caller = caller(0);
135              
136 5 50 33     20 my $build = current_build() || root_build(\$caller[0])
137             or croak "No current workflow build!";
138              
139 5         35 for my $task (@_) {
140 5 50       45 croak "include_workflow only accepts Test2::Workflow::Task objects, got: $task"
141             unless $task->isa('Test2::Workflow::Task');
142              
143 5         20 $build->add_primary($task);
144             }
145             }
146              
147             sub defaults {
148 646     646 0 1795 my %params = @_;
149              
150 646         1481 my ($package, $tool) = @params{qw/package tool/};
151              
152 646         1379 my @stack = (root_build($package), build_stack());
153 646 50       1337 return unless @stack;
154              
155 646         929 my %out;
156 646         1153 for my $build (@stack) {
157 1320 100       4062 %out = () if $build->stack_stop;
158 1320 100       5299 my $new = $build->defaults->{$tool} or next;
159 63         468 %out = (%out, %$new);
160             }
161              
162 646         4439 return \%out;
163             }
164              
165              
166             # Generate a bunch of subs that only have minor differences between them.
167             BEGIN {
168 44     44   409 @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 44         129 @EXPORT_OK = qw{
177             mini
178             iso miso
179             async masync
180             };
181              
182 44         1248 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 44         1010 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 4293 my ($tool, %params) = @_;
236 18         144 my @caller = caller(0);
237              
238             croak "'$tool' is not a spec tool"
239 18 0 33     81 unless exists $props{$tool} || exists $stages{$tool};
240              
241 18 50 33     72 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         216 $build->defaults->{$tool} = { %$old, %params };
246             }
247              
248 44         129 my $run = "";
249 44         135 for my $func (@EXPORT, @EXPORT_OK) {
250 748         1038 $run .= <<" EOT";
251 748         1276 #line ${ \(__LINE__ + 1) } "${ \__FILE__ }"
  748         3795  
252             sub $func {
253 27     27 1 356 my \@caller = caller(0);
  9     9 1 108  
  36     36 1 406  
  27     27 1 398  
  9     9 1 90  
  28     28 1 419  
  0     0 1 0  
  29     29 1 407  
  9     9 1 117  
  37     37 1 463  
  78     78 1 1125  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  358     358 1 16145  
254 27         125 my \$args = parse_args(args => \\\@_, caller => \\\@caller);
  9         45  
  36         133  
  27         123  
  9         36  
  28         114  
  0         0  
  29         142  
  9         45  
  37         142  
  78         307  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  358         1398  
255 27         106 my \$action = Test2::Workflow::Task::Action->new(\@{\$props{$func}}, %\$args);
  27         165  
  9         27  
  9         36  
  36         111  
  36         180  
  27         133  
  27         204  
  9         9  
  9         45  
  28         66  
  28         159  
  0         0  
  0         0  
  29         93  
  29         272  
  9         27  
  9         54  
  37         151  
  37         234  
  78         162  
  78         442  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  358         636  
  358         2074  
256              
257 27 50       199 return \$action if defined wantarray;
  9 50       72  
  36 50       220  
  27 50       179  
  9 50       63  
  28 50       168  
  0 0       0  
  29 50       222  
  9 50       54  
  37 50       245  
  78 50       436  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  358 100       1816  
258              
259 27 50 33     77 my \$build = current_build() || root_build(\$caller[0])
  9 50 33     36  
  36 50 33     113  
  27 50 33     78  
  9 50 33     27  
  28 50 33     86  
  0 0 0     0  
  29 50 33     106  
  9 50 33     27  
  37 50 33     122  
  78 50 33     236  
  0 0 0     0  
  0 0 0     0  
  0 0 0     0  
  0 0 0     0  
  0 0 0     0  
  357 50 66     958  
260             or croak "No current workflow build!";
261              
262 27 50       106 if (my \$defaults = defaults(package => \$caller[0], tool => '$func')) {
  9 50       90  
  36 50       147  
  27 50       92  
  9 50       36  
  28 50       91  
  0 0       0  
  29 50       127  
  9 50       27  
  37 50       122  
  78 50       255  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  357 50       996  
263 27         129 for my \$attr (keys \%\$defaults) {
  9         27  
  36         122  
  27         119  
  9         27  
  28         116  
  0         0  
  29         159  
  9         18  
  37         182  
  78         240  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  357         941  
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       126  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  72 50       243  
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         108  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  72         333  
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         54  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  72         315  
267             }
268             }
269              
270 27         46 \$build->\$_(\$action) for \@{\$stages{$func}};
  27         256  
  9         27  
  9         36  
  36         66  
  36         228  
  27         53  
  27         127  
  9         18  
  9         45  
  28         67  
  28         136  
  0         0  
  0         0  
  29         52  
  29         238  
  9         18  
  9         45  
  37         65  
  37         281  
  78         160  
  78         395  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  357         595  
  357         1864  
271             }
272             EOT
273             }
274              
275 44         163 my ($ok, $err);
276             {
277 44         98 local $@;
  44         97  
278 44         144870 $ok = eval "$run\n1";
279 44         156 $err = $@;
280             }
281              
282 44 50       1738 die $@ unless $ok;
283             }
284              
285             1;
286              
287             __END__