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   19950 use strict;
  44         83  
  44         1352  
3 44     44   227 use warnings;
  44         229  
  44         2063  
4              
5             our $VERSION = '0.000153';
6              
7 44     44   258 use Carp qw/croak/;
  44         186  
  44         2224  
8 44     44   17611 use Test2::Workflow qw/parse_args build current_build root_build init_root build_stack/;
  44         147  
  44         3430  
9              
10 44     44   299 use Test2::API qw/test2_add_callback_testing_done/;
  44         101  
  44         1860  
11              
12 44     44   20124 use Test2::Workflow::Runner();
  44         119  
  44         965  
13 44     44   361 use Test2::Workflow::Task::Action();
  44         91  
  44         720  
14 44     44   227 use Test2::Workflow::Task::Group();
  44         99  
  44         597  
15 44     44   196 use Test2::Tools::Mock();
  44         116  
  44         767  
16 44     44   232 use Test2::Util::Importer();
  44         112  
  44         1349  
17              
18 44     44   296 use vars qw/@EXPORT @EXPORT_OK/;
  44         90  
  44         28993  
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   555 my $class = shift;
25 43         389 my @caller = caller(0);
26              
27 43         207 my %root_args;
28             my %runner_args;
29 43         0 my @import;
30 43         236 while (my $arg = shift @_) {
31 39 100       200 if ($arg =~ s/^-//) {
32 12         24 my $val = shift @_;
33              
34 12 50       81 if (Test2::Workflow::Runner->can($arg)) {
    0          
    0          
    0          
35 12         68 $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       512 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         344 %root_args,
65             );
66              
67 43         245 my $runner = Test2::Workflow::Runner->new(%runner_args);
68              
69             Test2::Tools::Mock->add_handler(
70             $caller[0],
71             sub {
72 12     12   106 my %params = @_;
73 12         69 my ($class, $caller, $builder, $args) = @params{qw/class caller builder args/};
74              
75 12         1080 my $do_it = eval "package $caller->[0];\n#line $caller->[2] \"$caller->[1]\"\nsub { \$runner\->add_mock(\$builder->()) }";
76              
77             # Running
78 12 100       164 if (@{$runner->stack}) {
  12         56  
79 6         43 $do_it->();
80             }
81             else { # Not running
82 6         169 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     102 my $build = current_build() || $root;
90              
91 6         66 $build->add_primary_setup($action);
92 6 50       128 $build->add_stash($builder->()) unless $build->is_root;
93             }
94              
95 12         102 return 1;
96             }
97 43         664 );
98              
99             test2_add_callback_testing_done(
100             sub {
101 39 100   39   6821 return unless $root->populated;
102 37         252 my $g = $root->compile;
103 37         659 $runner->push_task($g);
104 37         525 $runner->run;
105             }
106 43         331 );
107             }
108              
109 43         1713 Test2::Util::Importer->import_into($class, $caller[0], @import);
110             }
111              
112             {
113 44     44   354 no warnings 'once';
  44         101  
  44         36171  
114             *cases = \&describe;
115             *include_workflows = \&include_workflow;
116             }
117              
118             sub describe {
119 92     92 0 7974 my @caller = caller(0);
120              
121 92         299 my $want = wantarray;
122              
123 92 100       1086 my $build = build(args => \@_, caller => \@caller, stack_stop => defined $want ? 1 : 0);
124              
125 87 100       399 return $build if defined $want;
126              
127 55 50 66     196 my $current = current_build() || root_build($caller[0])
128             or croak "No current workflow build!";
129              
130 55         281 $current->add_primary($build);
131             }
132              
133             sub include_workflow {
134 5     5 0 105 my @caller = caller(0);
135              
136 5 50 33     25 my $build = current_build() || root_build(\$caller[0])
137             or croak "No current workflow build!";
138              
139 5         40 for my $task (@_) {
140 5 50       40 croak "include_workflow only accepts Test2::Workflow::Task objects, got: $task"
141             unless $task->isa('Test2::Workflow::Task');
142              
143 5         25 $build->add_primary($task);
144             }
145             }
146              
147             sub defaults {
148 646     646 0 1958 my %params = @_;
149              
150 646         1580 my ($package, $tool) = @params{qw/package tool/};
151              
152 646         1456 my @stack = (root_build($package), build_stack());
153 646 50       1605 return unless @stack;
154              
155 646         978 my %out;
156 646         1270 for my $build (@stack) {
157 1320 100       4370 %out = () if $build->stack_stop;
158 1320 100       5668 my $new = $build->defaults->{$tool} or next;
159 63         432 %out = (%out, %$new);
160             }
161              
162 646         4289 return \%out;
163             }
164              
165              
166             # Generate a bunch of subs that only have minor differences between them.
167             BEGIN {
168 44     44   401 @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         118 @EXPORT_OK = qw{
177             mini
178             iso miso
179             async masync
180             };
181              
182 44         711 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         904 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 4824 my ($tool, %params) = @_;
236 18         144 my @caller = caller(0);
237              
238             croak "'$tool' is not a spec tool"
239 18 0 33     90 unless exists $props{$tool} || exists $stages{$tool};
240              
241 18 50 33     81 my $build = current_build() || root_build($caller[0])
242             or croak "No current workflow build!";
243              
244 18   50     81 my $old = $build->defaults->{$tool} ||= {};
245 18         180 $build->defaults->{$tool} = { %$old, %params };
246             }
247              
248 44         173 my $run = "";
249 44         162 for my $func (@EXPORT, @EXPORT_OK) {
250 748         1048 $run .= <<" EOT";
251 748         1377 #line ${ \(__LINE__ + 1) } "${ \__FILE__ }"
  748         3202  
252             sub $func {
253 27     27 1 396 my \@caller = caller(0);
  9     9 1 135  
  36     36 1 455  
  27     27 1 417  
  9     9 1 117  
  28     28 1 439  
  0     0 1 0  
  29     29 1 455  
  9     9 1 117  
  37     37 1 488  
  78     78 1 1240  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  358     358 1 15344  
254 27         114 my \$args = parse_args(args => \\\@_, caller => \\\@caller);
  9         63  
  36         153  
  27         130  
  9         45  
  28         232  
  0         0  
  29         154  
  9         54  
  37         164  
  78         339  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  358         1409  
255 27         93 my \$action = Test2::Workflow::Task::Action->new(\@{\$props{$func}}, %\$args);
  27         209  
  9         36  
  9         63  
  36         134  
  36         189  
  27         82  
  27         175  
  9         27  
  9         54  
  28         109  
  28         177  
  0         0  
  0         0  
  29         86  
  29         328  
  9         36  
  9         54  
  37         128  
  37         264  
  78         180  
  78         442  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  358         709  
  358         2131  
256              
257 27 50       161 return \$action if defined wantarray;
  9 50       54  
  36 50       202  
  27 50       201  
  9 50       63  
  28 50       197  
  0 0       0  
  29 50       189  
  9 50       63  
  37 50       229  
  78 50       498  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  358 100       1916  
258              
259 27 50 33     105 my \$build = current_build() || root_build(\$caller[0])
  9 50 33     36  
  36 50 33     112  
  27 50 33     101  
  9 50 33     45  
  28 50 33     105  
  0 0 0     0  
  29 50 33     122  
  9 50 33     36  
  37 50 33     154  
  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     1027  
260             or croak "No current workflow build!";
261              
262 27 50       95 if (my \$defaults = defaults(package => \$caller[0], tool => '$func')) {
  9 50       45  
  36 50       127  
  27 50       97  
  9 50       108  
  28 50       99  
  0 0       0  
  29 50       244  
  9 50       36  
  37 50       128  
  78 50       432  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  357 50       1041  
263 27         105 for my \$attr (keys \%\$defaults) {
  9         36  
  36         122  
  27         112  
  9         45  
  28         99  
  0         0  
  29         111  
  9         117  
  37         122  
  78         363  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  357         1018  
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       153  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  72 50       333  
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         99  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  72         324  
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         468  
267             }
268             }
269              
270 27         48 \$build->\$_(\$action) for \@{\$stages{$func}};
  27         153  
  9         27  
  9         72  
  36         65  
  36         223  
  27         64  
  27         156  
  9         27  
  9         63  
  28         86  
  28         154  
  0         0  
  0         0  
  29         73  
  29         225  
  9         27  
  9         72  
  37         114  
  37         220  
  78         174  
  78         430  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  357         594  
  357         1676  
271             }
272             EOT
273             }
274              
275 44         160 my ($ok, $err);
276             {
277 44         79 local $@;
  44         141  
278 44         138555 $ok = eval "$run\n1";
279 44         180 $err = $@;
280             }
281              
282 44 50       1725 die $@ unless $ok;
283             }
284              
285             1;
286              
287             __END__