File Coverage

blib/lib/Test/Subtests.pm
Criterion Covered Total %
statement 15 103 14.5
branch 0 26 0.0
condition 0 3 0.0
subroutine 5 19 26.3
pod 6 6 100.0
total 26 157 16.5


line stmt bran cond sub pod time code
1             package Test::Subtests;
2              
3 1     1   26757 use base 'Test::Builder::Module';
  1         3  
  1         141  
4             our @EXPORT = qw(one_of none_of some_of all_of most_of ignore);
5              
6 1     1   7 use Test::Builder;
  1         3  
  1         32  
7              
8 1     1   36 use 5.006;
  1         8  
  1         61  
9 1     1   6 use strict;
  1         2  
  1         50  
10 1     1   6 use warnings FATAL => 'all';
  1         2  
  1         1394  
11              
12             my $CLASS = __PACKAGE__;
13              
14             =head1 NAME
15              
16             Test::Subtests - Different kinds of subtests.
17              
18             =head1 VERSION
19              
20             Version 0.01
21              
22             =cut
23              
24             our $VERSION = '0.01';
25              
26             =head1 SYNOPSIS
27              
28             Different kinds of tests, that allow for some subtests to fail.
29              
30             use Test::More;
31             use Test::Subtests;
32              
33             one_of 'one_of fail' => sub { ok(1); ok(1); ok(0); };
34             one_of 'one_of pass' => sub { ok(1); ok(0); ok(0); };
35              
36             none_of 'none_of fail' => sub { ok(1); ok(1); ok(0); };
37             none_of 'none_of pass' => sub { ok(0); ok(0); ok(0); };
38              
39             some_of 'some_of fail' => sub { ok(0); ok(0); ok(0); };
40             some_of 'some_of pass' => sub { ok(1); ok(1); ok(0); };
41              
42             all_of 'all_of fail' => sub { ok(1); ok(1); ok(0); };
43             all_of 'all_of pass' => sub { ok(1); ok(1); ok(1); };
44              
45             most_of 'most_of fail' => sub { ok(1); ok(0); ok(0); };
46             most_of 'most_of pass' => sub { ok(1); ok(1); ok(0); };
47              
48             ignore 'ignore pass' => sub { ok(0); ok(0); ok(0); };
49             ignore 'ignore pass' => sub { ok(1); ok(1); ok(0); };
50              
51             =head1 EXPORT
52              
53             =over 4
54              
55             =item * C
56              
57             =item * C
58              
59             =item * C
60              
61             =item * C
62              
63             =item * C
64              
65             =item * C
66              
67             =back
68              
69             =head1 FUNCTIONS
70              
71             =cut
72              
73             # Run the subtests, and check the results
74             sub _subtest {
75             # Process arguments.
76 0     0     my ($name, $code, $check) = @_;
77              
78             # Get the caller's name.
79 0           my $caller = (caller(1))[3];
80 0           $caller =~ s/.*:://;
81              
82             # Get the test builder.
83 0           my $builder = $CLASS->builder;
84              
85             # Check the arguments $code and $check.
86 0 0         if ('CODE' ne ref $code) {
87 0           $builder->croak("$caller()'s second argument must be a code ref");
88             }
89 0 0         if ($check) {
90 0 0         if ('CODE' ne ref $check) {
91 0           $builder->croak("$caller()'s third argument must be a code ref'");
92             }
93             }
94              
95 0           my $error;
96             my $child;
97 0           my $parent = {};
98             {
99             # Override the level.
100 0           local $Test::Builder::Level = $Test::Builder::Level + 1;
  0            
101              
102             # Create a child test builder, and replace the parent by it.
103 0           $child = $builder->child($name);
104 0           Test::Builder::_copy($builder, $parent);
105 0           Test::Builder::_copy($child, $builder);
106              
107             # Run the subtests and catch the errors.
108             my $run_subtests = sub {
109 0     0     $builder->note("$caller: $name");
110 0           $code->();
111 0 0         $builder->done_testing unless $builder->_plan_handled;
112 0           return 1;
113 0           };
114 0 0         if (!eval { $run_subtests->() }) {
  0            
115 0           $error = $@;
116             }
117             }
118              
119             # Restore the child and parent test builders.
120 0           Test::Builder::_copy($builder, $child);
121 0           Test::Builder::_copy($parent, $builder);
122              
123             # Restore the parent's TODO.
124 0           $builder->find_TODO(undef, 1, $child->{Parent_TODO});
125              
126             # Die after the parent is restored.
127 0 0 0       die $error if $error and !eval { $error->isa('Test::Builder::Exception') };
  0            
128              
129             # Override the level.
130 0           local $Test::Builder::Level = $Test::Builder::Level + 1;
131              
132             # Check the results of the subtests.
133 0 0         if ($check) {
134 0           $child->no_ending(1);
135 0           $child->is_passing(&$check($child));
136             }
137              
138             # Finalize the child test builder.
139 0           my $finalize = $child->finalize;
140              
141             # Bail out if the child test builder bailed out.
142 0 0         $builder->BAIL_OUT($child->{Bailed_Out_Reason}) if $child->{Bailed_Out};
143              
144 0           return $finalize;
145             }
146              
147             =head2 one_of NAME, CODE
148              
149             Test that passes if exactly one subtest passes.
150              
151             =cut
152              
153             sub one_of {
154             # Process arguments.
155 0     0 1   my ($name, $code) = @_;
156              
157             # Define the check: only one subtest must pass.
158             my $check = sub {
159 0     0     my ($child) = @_;
160 0           my $count = 0;
161 0           foreach my $result (@{$child->{Test_Results}}) {
  0            
162 0 0         $count++ if $result->{ok};
163             }
164 0           return $count == 1;
165 0           };
166              
167             # Run the subtests.
168 0           return _subtest($name, $code, $check);
169             }
170              
171             =head2 none_of NAME, CODE
172              
173             Test that passes if all subtests fail.
174              
175             =cut
176              
177             sub none_of {
178             # Process arguments.
179 0     0 1   my ($name, $code) = @_;
180              
181             # Define the check: all subtests must fail.
182             my $check = sub {
183 0     0     my ($child) = @_;
184 0           my $count = 0;
185 0           foreach my $result (@{$child->{Test_Results}}) {
  0            
186 0 0         $count++ if $result->{ok};
187             }
188 0           return $count == 0;
189 0           };
190              
191             # Run the subtests.
192 0           return _subtest($name, $code, $check);
193             }
194              
195             =head2 some_of NAME, CODE
196              
197             Test that passes if at least one subtest passes.
198              
199             =cut
200              
201             sub some_of {
202             # Process arguments.
203 0     0 1   my ($name, $code) = @_;
204              
205             # Define the check: at least one subtest must pass.
206             my $check = sub {
207 0     0     my ($child) = @_;
208 0           my $count = 0;
209 0           foreach my $result (@{$child->{Test_Results}}) {
  0            
210 0 0         $count++ if $result->{ok};
211             }
212 0           return $count > 0;
213 0           };
214              
215             # Run the subtests.
216 0           return _subtest($name, $code, $check);
217             }
218              
219             =head2 all_of NAME, CODE
220              
221             Test that passes if all subtests pass.
222              
223             (Basically the same as C.)
224              
225             =cut
226              
227             sub all_of {
228             # Process arguments.
229 0     0 1   my ($name, $code) = @_;
230              
231             # Define the check: all subtests must pass.
232             my $check = sub {
233 0     0     my ($child) = @_;
234 0           my $count = 0;
235 0           foreach my $result (@{$child->{Test_Results}}) {
  0            
236 0 0         $count++ unless $result->{ok};
237             }
238 0           return $count == 0;
239 0           };
240              
241             # Run the subtests.
242 0           return _subtest($name, $code, $check);
243             }
244              
245             =head2 most_of NAME, CODE
246              
247             Test that passes if more subtests pass than fail.
248              
249             =cut
250              
251             sub most_of {
252             # Process arguments.
253 0     0 1   my ($name, $code) = @_;
254              
255             # Define the check: most subtests must pass.
256             my $check = sub {
257 0     0     my ($child) = @_;
258 0           my $pass = 0;
259 0           my $fail = 0;
260 0           foreach my $result (@{$child->{Test_Results}}) {
  0            
261 0 0         if ($result->{ok}) {
262 0           $pass++;
263             } else {
264 0           $fail++;
265             }
266             }
267 0           return $pass > $fail;
268 0           };
269              
270             # Run the subtests.
271 0           return _subtest($name, $code, $check);
272             }
273              
274             =head2 ignore NAME, CODE
275              
276             Test that ignores the results of the subtests. It always passes.
277              
278             =cut
279              
280             sub ignore {
281             # Process arguments.
282 0     0 1   my ($name, $code) = @_;
283              
284             # Define the check: always pass.
285             my $check = sub {
286 0     0     return 1;
287 0           };
288              
289             # Run the subtests.
290 0           return _subtest($name, $code, $check);
291             }
292              
293             =head1 AUTHOR
294              
295             Bert Vanderbauwhede, C<< >>
296              
297             =head1 BUGS
298              
299             Please report any bugs or feature requests to
300             C, or through the web interface at
301             L. I will be
302             notified, and then you'll automatically be notified of progress on your bug
303             as I make changes.
304              
305             =head1 SUPPORT
306              
307             You can find documentation for this module with the perldoc command.
308              
309             perldoc Test::Subtests
310              
311             You can also look for information at:
312              
313             =over 4
314              
315             =item * RT: CPAN's request tracker (report bugs here)
316              
317             L
318              
319             =item * AnnoCPAN: Annotated CPAN documentation
320              
321             L
322              
323             =item * CPAN Ratings
324              
325             L
326              
327             =item * Search CPAN
328              
329             L
330              
331             =back
332              
333             =head1 LICENSE AND COPYRIGHT
334              
335             Copyright 2014 Bert Vanderbauwhede.
336              
337             This program is free software; you can redistribute it and/or modify it under
338             the terms of the GNU Lesser General Public License as published by the Free
339             Software Foundation, either version 3 of the License, or (at your option)
340             any later version.
341              
342             See L for more information.
343              
344             =cut
345              
346             1; # End of Test::Subtests