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   19871 use strict;
  44         107  
  44         1306  
3 44     44   231 use warnings;
  44         102  
  44         2318  
4              
5             our $VERSION = '0.000155';
6              
7 44     44   262 use Carp qw/croak/;
  44         113  
  44         2799  
8 44     44   18001 use Test2::Workflow qw/parse_args build current_build root_build init_root build_stack/;
  44         94  
  44         3365  
9              
10 44     44   427 use Test2::API qw/test2_add_callback_testing_done/;
  44         115  
  44         2283  
11              
12 44     44   19782 use Test2::Workflow::Runner();
  44         132  
  44         952  
13 44     44   315 use Test2::Workflow::Task::Action();
  44         293  
  44         787  
14 44     44   257 use Test2::Workflow::Task::Group();
  44         197  
  44         639  
15 44     44   235 use Test2::Tools::Mock();
  44         128  
  44         819  
16 44     44   293 use Test2::Util::Importer();
  44         89  
  44         1017  
17              
18 44     44   210 use vars qw/@EXPORT @EXPORT_OK/;
  44         108  
  44         30942  
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   505 my $class = shift;
25 43         357 my @caller = caller(0);
26              
27 43         244 my %root_args;
28             my %runner_args;
29 43         0 my @import;
30 43         197 while (my $arg = shift @_) {
31 39 100       199 if ($arg =~ s/^-//) {
32 12         42 my $val = shift @_;
33              
34 12 50       78 if (Test2::Workflow::Runner->can($arg)) {
    0          
    0          
    0          
35 12         59 $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         99 push @import => $arg;
52             }
53             }
54              
55 43 50       585 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         374 %root_args,
65             );
66              
67 43         240 my $runner = Test2::Workflow::Runner->new(%runner_args);
68              
69             Test2::Tools::Mock->add_handler(
70             $caller[0],
71             sub {
72 12     12   103 my %params = @_;
73 12         54 my ($class, $caller, $builder, $args) = @params{qw/class caller builder args/};
74              
75 12         1371 my $do_it = eval "package $caller->[0];\n#line $caller->[2] \"$caller->[1]\"\nsub { \$runner\->add_mock(\$builder->()) }";
76              
77             # Running
78 12 100       204 if (@{$runner->stack}) {
  12         57  
79 6         37 $do_it->();
80             }
81             else { # Not running
82 6         148 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     69 my $build = current_build() || $root;
90              
91 6         57 $build->add_primary_setup($action);
92 6 50       87 $build->add_stash($builder->()) unless $build->is_root;
93             }
94              
95 12         113 return 1;
96             }
97 43         770 );
98              
99             test2_add_callback_testing_done(
100             sub {
101 39 100   39   6938 return unless $root->populated;
102 37         228 my $g = $root->compile;
103 37         568 $runner->push_task($g);
104 37         510 $runner->run;
105             }
106 43         308 );
107             }
108              
109 43         1602 Test2::Util::Importer->import_into($class, $caller[0], @import);
110             }
111              
112             {
113 44     44   373 no warnings 'once';
  44         100  
  44         37643  
114             *cases = \&describe;
115             *include_workflows = \&include_workflow;
116             }
117              
118             sub describe {
119 92     92 0 7919 my @caller = caller(0);
120              
121 92         260 my $want = wantarray;
122              
123 92 100       841 my $build = build(args => \@_, caller => \@caller, stack_stop => defined $want ? 1 : 0);
124              
125 87 100       469 return $build if defined $want;
126              
127 55 50 66     244 my $current = current_build() || root_build($caller[0])
128             or croak "No current workflow build!";
129              
130 55         285 $current->add_primary($build);
131             }
132              
133             sub include_workflow {
134 5     5 0 180 my @caller = caller(0);
135              
136 5 50 33     35 my $build = current_build() || root_build(\$caller[0])
137             or croak "No current workflow build!";
138              
139 5         50 for my $task (@_) {
140 5 50       60 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 1920 my %params = @_;
149              
150 646         1557 my ($package, $tool) = @params{qw/package tool/};
151              
152 646         1477 my @stack = (root_build($package), build_stack());
153 646 50       1397 return unless @stack;
154              
155 646         1002 my %out;
156 646         1324 for my $build (@stack) {
157 1320 100       4361 %out = () if $build->stack_stop;
158 1320 100       5825 my $new = $build->defaults->{$tool} or next;
159 63         558 %out = (%out, %$new);
160             }
161              
162 646         4932 return \%out;
163             }
164              
165              
166             # Generate a bunch of subs that only have minor differences between them.
167             BEGIN {
168 44     44   367 @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         148 @EXPORT_OK = qw{
177             mini
178             iso miso
179             async masync
180             };
181              
182 44         830 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         924 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 4653 my ($tool, %params) = @_;
236 18         153 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     90 my $old = $build->defaults->{$tool} ||= {};
245 18         234 $build->defaults->{$tool} = { %$old, %params };
246             }
247              
248 44         118 my $run = "";
249 44         161 for my $func (@EXPORT, @EXPORT_OK) {
250 748         1187 $run .= <<" EOT";
251 748         1397 #line ${ \(__LINE__ + 1) } "${ \__FILE__ }"
  748         3706  
252             sub $func {
253 27     27 1 429 my \@caller = caller(0);
  9     9 1 234  
  36     36 1 521  
  27     27 1 389  
  9     9 1 162  
  28     28 1 422  
  0     0 1 0  
  29     29 1 522  
  9     9 1 162  
  37     37 1 613  
  78     78 1 1227  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  358     358 1 17086  
254 27         159 my \$args = parse_args(args => \\\@_, caller => \\\@caller);
  9         81  
  36         193  
  27         211  
  9         72  
  28         130  
  0         0  
  29         195  
  9         72  
  37         195  
  78         324  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  358         1463  
255 27         94 my \$action = Test2::Workflow::Task::Action->new(\@{\$props{$func}}, %\$args);
  27         235  
  9         27  
  9         63  
  36         122  
  36         262  
  27         84  
  27         195  
  9         90  
  9         90  
  28         102  
  28         183  
  0         0  
  0         0  
  29         64  
  29         390  
  9         135  
  9         81  
  37         121  
  37         238  
  78         261  
  78         454  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  358         732  
  358         2156  
256              
257 27 50       249 return \$action if defined wantarray;
  9 50       90  
  36 50       397  
  27 50       319  
  9 50       72  
  28 50       247  
  0 0       0  
  29 50       184  
  9 50       144  
  37 50       287  
  78 50       503  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  358 100       1904  
258              
259 27 50 33     96 my \$build = current_build() || root_build(\$caller[0])
  9 50 33     36  
  36 50 33     133  
  27 50 33     140  
  9 50 33     36  
  28 50 33     114  
  0 0 0     0  
  29 50 33     145  
  9 50 33     45  
  37 50 33     197  
  78 50 33     314  
  0 0 0     0  
  0 0 0     0  
  0 0 0     0  
  0 0 0     0  
  0 0 0     0  
  357 50 66     994  
260             or croak "No current workflow build!";
261              
262 27 50       113 if (my \$defaults = defaults(package => \$caller[0], tool => '$func')) {
  9 50       81  
  36 50       118  
  27 50       139  
  9 50       45  
  28 50       101  
  0 0       0  
  29 50       225  
  9 50       36  
  37 50       179  
  78 50       308  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  357 50       1027  
263 27         130 for my \$attr (keys \%\$defaults) {
  9         63  
  36         124  
  27         192  
  9         45  
  28         92  
  0         0  
  29         156  
  9         54  
  37         226  
  78         326  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  357         1115  
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       117  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  72 50       225  
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         558  
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         324  
267             }
268             }
269              
270 27         53 \$build->\$_(\$action) for \@{\$stages{$func}};
  27         132  
  9         72  
  9         54  
  36         79  
  36         207  
  27         168  
  27         180  
  9         27  
  9         72  
  28         55  
  28         228  
  0         0  
  0         0  
  29         63  
  29         167  
  9         27  
  9         81  
  37         109  
  37         248  
  78         232  
  78         441  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  357         557  
  357         1543  
271             }
272             EOT
273             }
274              
275 44         146 my ($ok, $err);
276             {
277 44         80 local $@;
  44         98  
278 44         148272 $ok = eval "$run\n1";
279 44         189 $err = $@;
280             }
281              
282 44 50       1717 die $@ unless $ok;
283             }
284              
285             1;
286              
287             __END__