File Coverage

blib/lib/Test/Inline/Section.pm
Criterion Covered Total %
statement 120 132 90.9
branch 41 58 70.6
condition 22 36 61.1
subroutine 23 24 95.8
pod 14 14 100.0
total 220 264 83.3


line stmt bran cond sub pod time code
1             package Test::Inline::Section;
2             # ABSTRACT: Implements a section of tests
3              
4             #pod =pod
5             #pod
6             #pod =head1 DESCRIPTION
7             #pod
8             #pod This class implements a single section of tests. That is, a section of POD
9             #pod beginning with C<=begin test> or C<=begin testing>.
10             #pod
11             #pod =head2 Types of Sections
12             #pod
13             #pod There are two types of code sections. The first, beginning with
14             #pod C<=begin testing ...>, contains a set of tests and other code to be executed
15             #pod at any time (within a set of specifyable constraints). The second, labelled
16             #pod C<=begin testing SETUP>, contains code to be executed at the beginning of the
17             #pod test script, before any of the other sections are executed. This allows
18             #pod any needed variables or environment to be set up before the tests are run.
19             #pod You can have more than one setup section, and they will be written to the
20             #pod test file in order of appearance.
21             #pod
22             #pod =head2 Test Section Header Syntax
23             #pod
24             #pod Some examples of the different types of test headers are as follows.
25             #pod
26             #pod # Normal anonymous test
27             #pod =begin testing
28             #pod
29             #pod ok( $foo == $bar, 'This is a test' );
30             #pod
31             #pod =end testing
32             #pod
33             #pod # A named test. Also provides the number of tests to run.
34             #pod # Any test section can specify the number of tests.
35             #pod =begin testing my_method 1
36             #pod
37             #pod ok( $foo->my_method, '->my_method returns true' );
38             #pod
39             #pod =end testing
40             #pod
41             #pod # A named test with pre-requisites.
42             #pod # Note that ONLY named tests can have pre-requisites
43             #pod =begin testing this after my_method foo bar other_method Other::Class
44             #pod
45             #pod ok( $foo->this, '->this returns true' );
46             #pod
47             #pod =end testing
48             #pod
49             #pod The first example shows a normal anonymous test. All anonymous test sections
50             #pod are considered low priority, and we be run, in order of appearance, AFTER all
51             #pod named tests have been run.
52             #pod
53             #pod Any and all arguments used after "testing" must be in the form of simple
54             #pod space seperated words. The first word is considered the "name" of the test.
55             #pod The intended use for these is generally to create one named test section for
56             #pod each function or method, but you can name them as you please. Test names
57             #pod B be unique, and B case sensitive.
58             #pod
59             #pod After the name, you can provide the word "after" and provide a list of other
60             #pod named tests that must be completed first in order to run this test. This is
61             #pod provided so that when errors are encounted, they are probably the result of
62             #pod this method or set of tests, and not in some other method that this one
63             #pod relies on. It makes debugging a lot easier. The word after is only a
64             #pod keyword when after the test name, so you can use a test name of after as well.
65             #pod The following are both legal
66             #pod
67             #pod =begin testing after after that
68             #pod =begin testing this after after
69             #pod
70             #pod The easiest and recommended way of labeling the tests is simple to name all
71             #pod tests after their methods, and put as a pre-requisite any other methods that
72             #pod the method you are testing calls. Test::Inline will take care of writing the
73             #pod tests to the test script in the correct order. Please note you can NOT define
74             #pod circular relationships in the prerequisites, or an error will occur.
75             #pod
76             #pod If a number is provided as the last value, it will be taken to mean the
77             #pod number of actual tests that will occur during the test section. While
78             #pod preparing to write the test files, the processor will try to use these
79             #pod to try to determine the number of files to write. If ALL test sections to
80             #pod be written to a particular file have a test count, then the script will
81             #pod use the total of these as a basic for providing Test::More with a plan.
82             #pod
83             #pod If ANY test sections to be written to a file do not have a test count, the
84             #pod test file with use C.
85             #pod
86             #pod Finally, Test::Inline will try to be forgiving in it's parsing of the tests.
87             #pod any missing prerequisites will be ignored. Also, as long as it does not
88             #pod break a prerequisite, all named tests will be attempted to be run in their
89             #pod order of appearance.
90             #pod
91             #pod =head1 METHODS
92             #pod
93             #pod =cut
94              
95 12     12   85 use strict;
  12         26  
  12         345  
96 12     12   60 use List::Util ();
  12         22  
  12         215  
97 12     12   55 use Params::Util qw{_ARRAY};
  12         26  
  12         528  
98 12     12   68 use Algorithm::Dependency::Item ();
  12         22  
  12         26800  
99              
100             our $VERSION = '2.214';
101             our @ISA = 'Algorithm::Dependency::Item';
102             our $errstr = '';
103              
104              
105              
106              
107              
108             #####################################################################
109             # Constructor and Parsing
110              
111             #pod =pod
112             #pod
113             #pod =head2 new
114             #pod
115             #pod my $Section = Test::Inline::Section->new( $pod );
116             #pod
117             #pod The C constructor takes a string of POD, which must be a single section
118             #pod of relevant pod ( preferably produced by L ),
119             #pod and creates a new section object for it.
120             #pod
121             #pod Returns a new C object if passed POD in the form
122             #pod C<=begin testing ...>. Returns C on error.
123             #pod
124             #pod =cut
125              
126             my $RE_begin = qr/=begin\s+(?:test|testing)/;
127             my $RE_example = qr/=for\s+example\s+begin/;
128              
129             sub new {
130 57     57 1 5319 $errstr = '';
131 57         94 my $class = shift;
132 57 50       737 my $pod = $_[0] =~ /^(?:$RE_begin|$RE_example)\b/ ? shift :
133             return $class->_error("Test section does not begin with =begin test[ing]");
134 57         127 my $context = shift;
135              
136             # Split into lines
137 57         741 my @lines = split /(?:\015{1,2}\012|\015|\012)/, $pod;
138              
139             # Handle =for example seperately
140 57 100       354 if ( $pod =~ /^$RE_example\b/ ) {
141 1         4 return $class->_example( \@lines, $context );
142             }
143              
144             # Get the begin paragraph ( yes, paragraph. NOT line )
145 56         104 my $begin = '';
146 56   66     323 while ( @lines and $lines[0] !~ /^\s*$/ ) {
147 56 50       128 $begin .= ' ' if $begin;
148 56         311 $begin .= shift @lines;
149             }
150              
151             # Remove the trailing end tag
152 56 50 33     356 if ( @lines and $lines[-1] =~ /^=end\s+(?:test|testing)\b/o ) {
153 56         106 pop @lines;
154             }
155              
156             # Do some cleaning up and checking
157 56         193 $class->_trim_empty_lines( \@lines );
158 56 100       143 $class->_check_nesting( \@lines, $begin ) or return undef;
159              
160             # Create the basic object
161             my $self = bless {
162             begin => $begin,
163 55         125 content => join( '', map { "$_\n" } @lines ),
  57         541  
164             setup => '', # Is this a setup section
165             example => '', # Is this an example section
166             context => $context, # Package context
167             name => undef, # The name of the test
168             tests => undef, # undef means unknown test count
169             after => {}, # Other named methods this should be after
170             classes => {}, # Other classes this should be after
171             }, $class;
172              
173             # Start processing the begin line
174 55         349 my @parts = split /\s+/, $begin;
175              
176             # Remove the =begin
177 55         144 shift @parts;
178              
179             # If the line contains a number then this is part of the tests
180 55         168 foreach my $i ( 0 .. $#parts ) {
181 191 100       619 next unless $parts[$i] =~ /^(0|[1-9]\d*)$/;
182 43         167 $self->{tests} = splice @parts, $i, 1;
183 43         88 last;
184             }
185              
186             # Handle setup sections via =begin test setup or =begin testing SETUP
187 55 50 66     229 if ( @parts == 2 and $parts[0] eq 'test' and $parts[1] eq 'setup' ) {
      33        
188 0         0 $self->{setup} = 1;
189             }
190 55 100 66     296 if ( @parts >= 2 and $parts[0] eq 'testing' and $parts[1] eq 'SETUP' ) {
      100        
191 9         31 $self->{setup} = 1;
192             }
193              
194             # Any other form of =begin test is not allowed
195 55 50 33     155 if ( $parts[0] eq 'test' and ! $self->{setup} ) {
196             # Unknown =begin test line
197 0         0 return $class->_error("Unsupported '=begin test' line '$begin'");
198             }
199              
200             # Remove the "testing" word
201 55         82 shift @parts;
202              
203             # If there are no remaining parts, we are anonymous,
204             # and can just return as is.
205 55 100       147 return $self unless @parts;
206              
207             # Make sure all remaining parts are only words
208 46 50       85 if ( grep { ! /^[\w:]+$/ } @parts ) {
  93         368  
209 0         0 return $class->_error("Found something other than words: $begin");
210             }
211              
212             # The first word is our name and must match the perl
213             # format for a method name.
214 46 100       129 if ( $self->{setup} ) {
215 9         18 shift @parts;
216             } else {
217 37         73 $self->{name} = shift @parts;
218 37 50       174 unless ( $self->{name} =~ /^[^\W\d]\w*$/ ) {
219 0         0 return $class->_error("'$self->{name}' is not a valid test name: $begin");
220             }
221             }
222 46 100       173 return $self unless @parts;
223              
224             # The next word MUST be "after"
225 19 50       53 unless ( shift @parts eq 'after' ) {
226 0         0 return $class->_error("Word after test name is something other than 'after': $begin");
227             }
228              
229             # The remaining words are our dependencies.
230             # Simple words chunks are method dependencies, and anything
231             # containing :: (including at the end) is a dependency on
232             # another module that should be part of the testing process.
233 19         56 foreach my $part ( @parts ) {
234 28 100       102 if ( $part =~ /^[^\W\d]\w*$/ ) {
    50          
235 26 50       63 if ( $self->setup ) {
236 0         0 return $class->_error("SETUP sections can only have class dependencies");
237             }
238 26         81 $self->{after}->{$part} = 1;
239             } elsif ( $part =~ /::/ ) {
240 2         6 $part =~ s/::$//; # Strip trailing ::
241 2         7 $self->{classes}->{$part} = 1;
242             } else {
243 0         0 return $class->_error("Unknown dependency '$part' in begin line: $begin");
244             }
245             }
246              
247 19         69 $self;
248             }
249              
250             # Handle the creation of example sections
251             sub _example {
252 1     1   2 my $class = shift;
253 1         2 my @lines = @{shift()};
  1         4  
254 1         2 my $context = shift;
255              
256             # Get the begin paragraph ( yes, paragraph. NOT line )
257 1         2 my $begin = '';
258 1   66     8 while ( @lines and $lines[0] !~ /^\s*$/ ) {
259 1 50       3 $begin .= ' ' if $begin;
260 1         5 $begin .= shift @lines;
261             }
262              
263             # Remove the trailing end tag
264 1 50 33     8 if ( @lines and $lines[-1] =~ /^=for\s+example\s+end\b/o ) {
265 1         3 pop @lines;
266             }
267              
268             # Remove any leading and trailing empty lines
269 1         4 $class->_trim_empty_lines( \@lines );
270 1 50       3 $class->_check_nesting( \@lines, $begin ) or return undef;
271              
272             # Create the basic object
273             my $self = bless {
274             begin => $begin,
275 1         4 content => join( '', map { "$_\n" } @lines ),
  2         13  
276             setup => '', # Is this a setup section
277             example => 1, # Is this an example section
278             context => $context, # Package context
279             name => undef, # Examples arn't named
280             tests => 1, # An example always consumes 1 test
281             after => {}, # Other named methods this should be after
282             classes => {}, # Other classes this should be after
283             }, $class;
284              
285 1         5 $self;
286             }
287              
288             sub _error {
289 1     1   13 $errstr = join ': ', @_;
290 1         19 undef;
291             }
292              
293             sub _short {
294 2     2   4 my $either = shift;
295 2         4 my $string = shift;
296 2         5 chomp $string;
297 2         6 $string =~ s/\n/ /g;
298 2 50       6 if ( length($string) > 30 ) {
299 0         0 $string = substr($string, 27);
300 0         0 $string =~ s/\s+$//;
301 0         0 $string .= '...';
302             }
303 2         4 $string;
304             }
305              
306             sub _check_nesting {
307 57     57   148 my ($class, $lines, $begin) = @_;
308              
309             # In the remaining lines there shouldn't be any lines
310             # that look like a POD tag. If there is there is probably
311             # a nesting problem.
312 57     62   300 my $bad_line = List::Util::first { /^=\w+/ } @$lines;
  62         148  
313 57 100       191 if ( $bad_line ) {
314 1         5 $bad_line = $class->_short($bad_line);
315 1         4 $begin = $class->_short($begin);
316 1         7 return $class->_error(
317             "POD statement '$bad_line' illegally nested inside of section '$begin'"
318             );
319             }
320              
321 56         156 1;
322             }
323              
324             sub _trim_empty_lines {
325 57     57   92 my $lines = $_[1];
326 57   66     232 while ( @$lines and $lines->[0] eq '' ) { shift @$lines }
  57         198  
327 57   66     217 while ( @$lines and $lines->[-1] eq '' ) { pop @$lines }
  57         203  
328 57         94 1;
329             }
330              
331              
332              
333              
334              
335             #####################################################################
336             # Main Methods
337              
338             #pod =pod
339             #pod
340             #pod =head2 parse
341             #pod
342             #pod my $SectionList = Test::Inline::Section( @elements );
343             #pod
344             #pod Since version 1.50 L has been extracting package statements
345             #pod so that as the sections are extracted, we can determine which sections
346             #pod belong to which packages, and seperate them accordingly.
347             #pod
348             #pod The C method takes B of the elements from a file, and returns
349             #pod all of the Sections. By doing it here, we can track the package context
350             #pod and set it in the Sections.
351             #pod
352             #pod =cut
353              
354             sub parse {
355 17     17 1 48 $errstr = '';
356 17         38 my $class = shift;
357 17 50       85 my $elements = _ARRAY(shift) or return undef;
358 17         43 my @Sections = ();
359              
360             # Iterate over the elements and maintain package contexts
361 17         35 my $context = '';
362 17         48 foreach my $element ( @$elements ) {
363 71 100       216 if ( $element =~ /^package\s+([\w:']+)/ ) {
364 21         52 $context = $1;
365 21         48 next;
366             }
367              
368             # Handle weird unexpected elements
369 50 50       153 unless ( $element =~ /^=/ ) {
370 0         0 return $class->_error("Unexpected element '$element'");
371             }
372              
373             # Hand off to the Section constructor
374 50 100       155 my $Section = Test::Inline::Section->new( $element, $context ) or return undef;
375 49         144 push @Sections, $Section;
376             }
377              
378 16 50       108 @Sections ? \@Sections : undef;
379             }
380              
381             #pod =pod
382             #pod
383             #pod =head2 setup
384             #pod
385             #pod my $run_first = $Section->setup;
386             #pod
387             #pod The C accessor indicates that this section is a "setup" section,
388             #pod to be run at the beginning of the generated test script.
389             #pod
390             #pod Returns true if this is a setup section, false otherwise.
391             #pod
392             #pod =cut
393              
394 173     173 1 2987 sub setup { $_[0]->{setup} }
395              
396             #pod =pod
397             #pod
398             #pod =head2 example
399             #pod
400             #pod my $just_compile = $Section->example;
401             #pod
402             #pod The C accessor indicates that this section is an "example"
403             #pod section, to be compile-tested instead of run.
404             #pod
405             #pod Returns true if this is an example section, false otherwise.
406             #pod
407             #pod =cut
408              
409 44     44 1 139 sub example { $_[0]->{example} }
410              
411             #pod =pod
412             #pod
413             #pod =head2 context
414             #pod
415             #pod The C method returns the package context of the unit test section,
416             #pod or false if the unit test section appeared out of context.
417             #pod
418             #pod =cut
419              
420 54     54 1 180 sub context { $_[0]->{context} }
421              
422             #pod =pod
423             #pod
424             #pod =head2 name
425             #pod
426             #pod The C method returns the name of the test section,
427             #pod or false if the test if anonymous.
428             #pod
429             #pod =cut
430              
431 485 100   485 1 1627 sub name { defined $_[0]->{name} and $_[0]->{name} }
432              
433             #pod =pod
434             #pod
435             #pod =head2 tests
436             #pod
437             #pod The C method returns the number of Test::Builder-compatible
438             #pod tests that will run within the test section. Returns C if the
439             #pod number of tests is unknown.
440             #pod
441             #pod =cut
442              
443 202     202 1 577 sub tests { $_[0]->{tests} }
444              
445             #pod =pod
446             #pod
447             #pod =head2 begin
448             #pod
449             #pod For use mainly in debugging, the C method returns the literal string
450             #pod of the begin line/paragraph.
451             #pod
452             #pod =cut
453              
454 0     0 1 0 sub begin { $_[0]->{begin} }
455              
456             #pod =pod
457             #pod
458             #pod =head2 anonymous
459             #pod
460             #pod my $is_anonymous = $Section->anonymous;
461             #pod
462             #pod The C method returns true if the test section is an unnamed
463             #pod anonymous section, or false if it is a named section or a setup section.
464             #pod
465             #pod =cut
466              
467             sub anonymous {
468 29     29 1 45 my $self = shift;
469 29   100     124 ! (defined $self->{name} or $self->{setup});
470             }
471              
472             #pod =pod
473             #pod
474             #pod =head2 after
475             #pod
476             #pod my @names = $Section->after;
477             #pod
478             #pod The C method returns the list of other named tests that this
479             #pod test section says it should be run after.
480             #pod
481             #pod Returns a list of test name, or the null list C<()> if the test does
482             #pod not have to run after any other named tests.
483             #pod
484             #pod =cut
485              
486             sub after {
487 130     130 1 1982 keys %{$_[0]->{after}};
  130         522  
488             }
489              
490             #pod =pod
491             #pod
492             #pod =head2 classes
493             #pod
494             #pod my @classes = $Section->classes;
495             #pod
496             #pod The C method returns the list of test classes that the test depends
497             #pod on, and should be run before the tests. These values are used to determine the
498             #pod set of class-level dependencies for the entire test file.
499             #pod
500             #pod Returns a list of class names, or the null list C<()> if the test does
501             #pod not have any class-level dependencies.
502             #pod
503             #pod =cut
504              
505             sub classes {
506 47     47 1 443 keys %{$_[0]->{classes}};
  47         124  
507             }
508              
509             #pod =pod
510             #pod
511             #pod =head2 content
512             #pod
513             #pod my $code = $Section->content;
514             #pod
515             #pod The C method returns the actual testing code contents of the
516             #pod section, with the leading C<=begin> and trailing C<=end> removed.
517             #pod
518             #pod Returns a string containing the code, or the null string C<""> if the
519             #pod section was empty.
520             #pod
521             #pod =cut
522              
523 91     91 1 316 sub content { $_[0]->{content} }
524              
525              
526              
527              
528              
529             #####################################################################
530             # Implementing the Algorithm::Dependency::Item interface
531              
532             # The ->depends method we have works the same as for
533             # Algorithm::Dependency::Item already, so we just need to implement
534             # it's ->id method, which is the same as our ->name method
535              
536 18     18 1 68 sub id { $_[0]->name }
537 125     125 1 530 sub depends { $_[0]->after }
538              
539             1;
540              
541             __END__