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   3886323 use strict;
  43         52  
  43         937  
3 43     43   129 use warnings;
  43         42  
  43         840  
4              
5 43     43   117 use Carp qw/croak/;
  43         72  
  43         1626  
6 43     43   12407 use Test2::Workflow qw/parse_args build current_build root_build init_root build_stack/;
  43         56  
  43         2405  
7              
8 43     43   14701 use Test2::Workflow::Runner();
  43         92  
  43         697  
9 43     43   200 use Test2::Workflow::Task::Action();
  43         43  
  43         419  
10 43     43   128 use Test2::Workflow::Task::Group();
  43         46  
  43         410  
11 43     43   127 use Test2::Tools::Mock();
  43         53  
  43         378  
12 43     43   128 use Importer();
  43         45  
  43         561  
13              
14 43     43   116 use vars qw/@EXPORT @EXPORT_OK/;
  43         44  
  43         18848  
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   318 my $class = shift;
21 42         246 my @caller = caller(0);
22              
23 42         58 my %root_args;
24             my %runner_args;
25 0         0 my @import;
26 42         150 while (my $arg = shift @_) {
27 39 100       130 if ($arg =~ s/^-//) {
28 12         14 my $val = shift @_;
29              
30 12 50       93 if (Test2::Workflow::Runner->can($arg)) {
    0          
    0          
    0          
31 12         46 $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         72 push @import => $arg;
48             }
49             }
50              
51 42 50       133 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         286 %root_args,
61             );
62              
63 42         171 my $runner = Test2::Workflow::Runner->new(%runner_args);
64              
65             Test2::Tools::Mock->add_handler(
66             $caller[0],
67             sub {
68 12     12   2911 my %params = @_;
69 12         34 my ($class, $caller, $builder, $args) = @params{qw/class caller builder args/};
70              
71 12         873 my $do_it = eval "package $caller->[0];\n#line $caller->[2] \"$caller->[1]\"\nsub { \$runner\->add_mock(\$builder->()) }";
72              
73             # Running
74 12 100       102 if (@{$runner->stack}) {
  12         52  
75 6         27 $do_it->();
76             }
77             else { # Not running
78 6         108 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     30 my $build = current_build() || $root;
86              
87 6         38 $build->add_primary_setup($action);
88 6 50       64 $build->add_stash($builder->()) unless $build->is_root;
89             }
90              
91 12         58 return 1;
92             }
93 42         618 );
94              
95 42         444 my $stack = Test2::API::test2_stack;
96 42         398 $stack->top; # Insure we have a hub
97 42         1262517 my ($hub) = Test2::API::test2_stack->all;
98 42         561 $hub->set_active(1);
99             $hub->follow_up(
100             sub {
101 38 100   38   270913 return unless $root->populated;
102 36         152 my $g = $root->compile;
103 36         311 $runner->push_task($g);
104 36         275 $runner->run;
105             }
106 42         438 );
107             }
108              
109 42         775 Importer->import_into($class, $caller[0], @import);
110             }
111              
112             {
113 43     43   178 no warnings 'once';
  43         862  
  43         22469  
114             *cases = \&describe;
115             *include_workflows = \&include_workflow;
116             }
117              
118             sub describe {
119 91     91 0 5112 my @caller = caller(0);
120              
121 91         136 my $want = wantarray;
122              
123 91 100       475 my $build = build(args => \@_, caller => \@caller, stack_stop => defined $want ? 1 : 0);
124              
125 86 100       257 return $build if defined $want;
126              
127 54 50 66     145 my $current = current_build() || root_build($caller[0])
128             or croak "No current workflow build!";
129              
130 54         140 $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         25 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         25 $build->add_primary($task);
144             }
145             }
146              
147             sub defaults {
148 642     642 0 1114 my %params = @_;
149              
150 642         861 my ($package, $tool) = @params{qw/package tool/};
151              
152 642         952 my @stack = (root_build($package), build_stack());
153 642 50       954 return unless @stack;
154              
155 642         487 my %out;
156 642         766 for my $build (@stack) {
157 1313 100       2902 %out = () if $build->stack_stop;
158 1313 100       3892 my $new = $build->defaults->{$tool} or next;
159 63         270 %out = (%out, %$new);
160             }
161              
162 642         2815 return \%out;
163             }
164              
165              
166             # Generate a bunch of subs that only have minor differences between them.
167             BEGIN {
168 43     43   140 @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         72 @EXPORT_OK = qw{
177             mini
178             iso miso
179             async masync
180             };
181              
182 43         577 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         493 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 783 my ($tool, %params) = @_;
236 18         99 my @caller = caller(0);
237              
238             croak "'$tool' is not a spec tool"
239 18 0 33     45 unless exists $props{$tool} || exists $stages{$tool};
240              
241 18 50 33     45 my $build = current_build() || root_build($caller[0])
242             or croak "No current workflow build!";
243              
244 18   50     54 my $old = $build->defaults->{$tool} ||= {};
245 18         144 $build->defaults->{$tool} = { %$old, %params };
246             }
247              
248 43         62 my $run = "";
249 43         96 for my $func (@EXPORT, @EXPORT_OK) {
250 731         380 $run .= <<" EOT";
251 731         751 #line ${ \(__LINE__ + 1) } "${ \__FILE__ }"
  731         1778  
252             sub $func {
253 27     27 1 252 my \@caller = caller(0);
  9     9 1 72  
  36     36 1 283  
  27     27 1 216  
  9     9 1 81  
  28     28 1 567  
  0     0 1 0  
  28     28 1 272  
  9     9 1 90  
  37     37 1 338  
  78     78 1 654  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  355     355 1 8676  
254 27         83 my \$args = parse_args(args => \\\@_, caller => \\\@caller);
  9         36  
  36         112  
  27         83  
  9         27  
  28         87  
  0         0  
  28         101  
  9         36  
  37         103  
  78         195  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  355         942  
255 27         33 my \$action = Test2::Workflow::Task::Action->new(\@{\$props{$func}}, %\$args);
  27         104  
  9         18  
  9         36  
  36         53  
  36         140  
  27         37  
  27         100  
  9         9  
  9         450  
  28         28  
  28         96  
  0         0  
  0         0  
  28         43  
  28         217  
  9         18  
  9         45  
  37         48  
  37         158  
  78         95  
  78         291  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  355         385  
  355         1617  
256              
257 27 50       111 return \$action if defined wantarray;
  9 50       36  
  36 50       136  
  27 50       103  
  9 50       45  
  28 50       104  
  0 0       0  
  28 50       115  
  9 50       45  
  37 50       160  
  78 50       276  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  355 100       1304  
258              
259 27 50 33     66 my \$build = current_build() || root_build(\$caller[0])
  9 50 33     27  
  36 50 33     69  
  27 50 33     67  
  9 50 33     27  
  28 50 33     67  
  0 0 0     0  
  28 50 33     70  
  9 50 33     27  
  37 50 33     84  
  78 50 33     156  
  0 0 0     0  
  0 0 0     0  
  0 0 0     0  
  0 0 0     0  
  0 0 0     0  
  354 50 66     670  
260             or croak "No current workflow build!";
261              
262 27 50       56 if (my \$defaults = defaults(package => \$caller[0], tool => '$func')) {
  9 50       18  
  36 50       69  
  27 50       56  
  9 50       18  
  28 50       58  
  0 0       0  
  28 50       69  
  9 50       18  
  37 50       70  
  78 50       217  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  354 50       617  
263 27         80 for my \$attr (keys \%\$defaults) {
  9         27  
  36         72  
  27         61  
  9         18  
  28         58  
  0         0  
  28         68  
  9         27  
  37         83  
  78         158  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  354         720  
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       171  
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         63  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  72         225  
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         135  
267             }
268             }
269              
270 27         27 \$build->\$_(\$action) for \@{\$stages{$func}};
  27         102  
  9         9  
  9         36  
  36         42  
  36         154  
  27         26  
  27         99  
  9         18  
  9         36  
  28         36  
  28         110  
  0         0  
  0         0  
  28         35  
  28         122  
  9         18  
  9         45  
  37         40  
  37         178  
  78         101  
  78         252  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  354         295  
  354         1179  
271             }
272             EOT
273             }
274              
275 43         53 my ($ok, $err);
276             {
277 43         218 local $@;
  43         63  
278 43         83336 $ok = eval "$run\n1";
279 43         85 $err = $@;
280             }
281              
282 43 50       1001 die $@ unless $ok;
283             }
284              
285             1;
286              
287             __END__