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   5453152 use strict;
  43         65  
  43         988  
3 43     43   131 use warnings;
  43         44  
  43         885  
4              
5 43     43   132 use Carp qw/croak/;
  43         72  
  43         1773  
6 43     43   13234 use Test2::Workflow qw/parse_args build current_build root_build init_root build_stack/;
  43         66  
  43         2606  
7              
8 43     43   15769 use Test2::Workflow::Runner();
  43         72  
  43         754  
9 43     43   216 use Test2::Workflow::Task::Action();
  43         45  
  43         433  
10 43     43   138 use Test2::Workflow::Task::Group();
  43         42  
  43         770  
11 43     43   138 use Test2::Tools::Mock();
  43         55  
  43         426  
12 43     43   139 use Importer();
  43         45  
  43         553  
13              
14 43     43   910 use vars qw/@EXPORT @EXPORT_OK/;
  43         57  
  43         20595  
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   428 my $class = shift;
21 42         274 my @caller = caller(0);
22              
23 42         56 my %root_args;
24             my %runner_args;
25 0         0 my @import;
26 42         175 while (my $arg = shift @_) {
27 39 100       129 if ($arg =~ s/^-//) {
28 12         13 my $val = shift @_;
29              
30 12 50       83 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       154 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         337 %root_args,
61             );
62              
63 42         173 my $runner = Test2::Workflow::Runner->new(%runner_args);
64              
65             Test2::Tools::Mock->add_handler(
66             $caller[0],
67             sub {
68 12     12   3727 my %params = @_;
69 12         34 my ($class, $caller, $builder, $args) = @params{qw/class caller builder args/};
70              
71 12         881 my $do_it = eval "package $caller->[0];\n#line $caller->[2] \"$caller->[1]\"\nsub { \$runner\->add_mock(\$builder->()) }";
72              
73             # Running
74 12 100       98 if (@{$runner->stack}) {
  12         49  
75 6         28 $do_it->();
76             }
77             else { # Not running
78 6         101 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     31 my $build = current_build() || $root;
86              
87 6         35 $build->add_primary_setup($action);
88 6 50       50 $build->add_stash($builder->()) unless $build->is_root;
89             }
90              
91 12         86 return 1;
92             }
93 42         526 );
94              
95 42         510 my $stack = Test2::API::test2_stack;
96 42         428 $stack->top; # Insure we have a hub
97 42         1315123 my ($hub) = Test2::API::test2_stack->all;
98 42         591 $hub->set_active(1);
99             $hub->follow_up(
100             sub {
101 38 100   38   304202 return unless $root->populated;
102 36         144 my $g = $root->compile;
103 36         296 $runner->push_task($g);
104 36         230 $runner->run;
105             }
106 42         451 );
107             }
108              
109 42         829 Importer->import_into($class, $caller[0], @import);
110             }
111              
112             {
113 43     43   180 no warnings 'once';
  43         52  
  43         23388  
114             *cases = \&describe;
115             *include_workflows = \&include_workflow;
116             }
117              
118             sub describe {
119 91     91 0 6401 my @caller = caller(0);
120              
121 91         131 my $want = wantarray;
122              
123 91 100       523 my $build = build(args => \@_, caller => \@caller, stack_stop => defined $want ? 1 : 0);
124              
125 86 100       414 return $build if defined $want;
126              
127 54 50 66     126 my $current = current_build() || root_build($caller[0])
128             or croak "No current workflow build!";
129              
130 54         159 $current->add_primary($build);
131             }
132              
133             sub include_workflow {
134 5     5 0 110 my @caller = caller(0);
135              
136 5 50 33     30 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         15 $build->add_primary($task);
144             }
145             }
146              
147             sub defaults {
148 642     642 0 1098 my %params = @_;
149              
150 642         779 my ($package, $tool) = @params{qw/package tool/};
151              
152 642         1075 my @stack = (root_build($package), build_stack());
153 642 50       1461 return unless @stack;
154              
155 642         493 my %out;
156 642         735 for my $build (@stack) {
157 1313 100       3010 %out = () if $build->stack_stop;
158 1313 100       4037 my $new = $build->defaults->{$tool} or next;
159 63         279 %out = (%out, %$new);
160             }
161              
162 642         2991 return \%out;
163             }
164              
165              
166             # Generate a bunch of subs that only have minor differences between them.
167             BEGIN {
168 43     43   161 @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         75 @EXPORT_OK = qw{
177             mini
178             iso miso
179             async masync
180             };
181              
182 43         845 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         502 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         117 my @caller = caller(0);
237              
238             croak "'$tool' is not a spec tool"
239 18 0 33     63 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     54 my $old = $build->defaults->{$tool} ||= {};
245 18         162 $build->defaults->{$tool} = { %$old, %params };
246             }
247              
248 43         100 my $run = "";
249 43         111 for my $func (@EXPORT, @EXPORT_OK) {
250 731         830 $run .= <<" EOT";
251 731         813 #line ${ \(__LINE__ + 1) } "${ \__FILE__ }"
  731         1792  
252             sub $func {
253 27     27 1 278 my \@caller = caller(0);
  9     9 1 81  
  36     36 1 373  
  27     27 1 248  
  9     9 1 99  
  28     28 1 710  
  0     0 1 0  
  28     28 1 304  
  9     9 1 81  
  37     37 1 355  
  78     78 1 726  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  0     0 1 0  
  355     355 1 8748  
254 27         101 my \$args = parse_args(args => \\\@_, caller => \\\@caller);
  9         27  
  36         111  
  27         88  
  9         36  
  28         92  
  0         0  
  28         101  
  9         36  
  37         118  
  78         248  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  355         1061  
255 27         46 my \$action = Test2::Workflow::Task::Action->new(\@{\$props{$func}}, %\$args);
  27         102  
  9         18  
  9         45  
  36         49  
  36         142  
  27         40  
  27         130  
  9         9  
  9         45  
  28         42  
  28         106  
  0         0  
  0         0  
  28         40  
  28         224  
  9         18  
  9         36  
  37         57  
  37         176  
  78         97  
  78         318  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  355         387  
  355         1594  
256              
257 27 50       114 return \$action if defined wantarray;
  9 50       54  
  36 50       137  
  27 50       110  
  9 50       45  
  28 50       118  
  0 0       0  
  28 50       116  
  9 50       54  
  37 50       172  
  78 50       295  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  355 100       1233  
258              
259 27 50 33     63 my \$build = current_build() || root_build(\$caller[0])
  9 50 33     18  
  36 50 33     83  
  27 50 33     69  
  9 50 33     18  
  28 50 33     65  
  0 0 0     0  
  28 50 33     82  
  9 50 33     18  
  37 50 33     96  
  78 50 33     130  
  0 0 0     0  
  0 0 0     0  
  0 0 0     0  
  0 0 0     0  
  0 0 0     0  
  354 50 66     696  
260             or croak "No current workflow build!";
261              
262 27 50       54 if (my \$defaults = defaults(package => \$caller[0], tool => '$func')) {
  9 50       18  
  36 50       61  
  27 50       64  
  9 50       27  
  28 50       66  
  0 0       0  
  28 50       97  
  9 50       27  
  37 50       73  
  78 50       156  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  0 0       0  
  354 50       806  
263 27         64 for my \$attr (keys \%\$defaults) {
  9         27  
  36         84  
  27         70  
  9         36  
  28         70  
  0         0  
  28         72  
  9         27  
  37         90  
  78         147  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  354         627  
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       198  
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         198  
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         171  
267             }
268             }
269              
270 27         40 \$build->\$_(\$action) for \@{\$stages{$func}};
  27         137  
  9         9  
  9         27  
  36         39  
  36         226  
  27         25  
  27         120  
  9         9  
  9         36  
  28         45  
  28         204  
  0         0  
  0         0  
  28         26  
  28         144  
  9         18  
  9         549  
  37         49  
  37         153  
  78         93  
  78         297  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  354         373  
  354         1245  
271             }
272             EOT
273             }
274              
275 43         56 my ($ok, $err);
276             {
277 43         44 local $@;
  43         60  
278 43         86696 $ok = eval "$run\n1";
279 43         106 $err = $@;
280             }
281              
282 43 50       1054 die $@ unless $ok;
283             }
284              
285             1;
286              
287             __END__