1Pod::Snippets(3) User Contributed Perl Documentation Pod::Snippets(3)
2
3
4
6 Pod::Snippets - Extract and reformat snippets of POD so as to use them
7 in a unit test (or other Perl code)
8
10 Version 0.14
11
13 use Pod::Snippets;
14
15 my $snips = load Pod::Snippets($file_or_handle,
16 -markup => "test");
17
18 my $code_snippet = $snips->named("synopsis")->as_code;
19
20 # ... Maybe borg $code_snippet with regexes or something...
21
22 my $result = eval $code_snippet; die $@ if $@;
23
24 like($result->what_happen(), qr/bomb/);
25
26 The Perl code that we want to extract snippets from might look like
27 this:
28
29 package Zero::Wing;
30
31 =head1 NAME
32
33 Zero::Wing - For great justice!
34
35 =head1 SYNOPSIS
36
37 =for test "synopsis" begin
38
39 use Zero::Wing;
40
41 my $capitain = Zero::Wing->capitain;
42
43 =for test "synopsis" end
44
45 =cut
46
47 # ...
48
49 1;
50
52 This class is a very simple extension of Pod::Parser that extracts POD
53 snippets from Perl code, and pretty-prints it so as to make it useable
54 from other Perl code. As demonstrated above, Pod::Snipets is
55 immediately useful to test-driven-development nutcases who want to put
56 every single line of Perl code under test, including code that is in
57 the POD (typically a SYNOPSIS section). There are other uses, such as
58 storing a piece of information that is both human- and machine-readable
59 (eg an XML schema) simultaneously as documentation and code.
60
61 Using Pod::Snippets for unit testing
62 The "SYNOPSIS" demonstrates how to use Pod::Snippets to grab a piece of
63 POD and execute it with "eval" in perlfunc. This can readily be done
64 using your usual unit testing methodology, without too much ajusting if
65 any. This approach has some advantages over other code-in-POD devices
66 such as Pod::Tested and Test::Inline:
67
68 · There is no preprocessing step involved, hence no temp files and no
69 loss of hair in the debugger due to line renumbering.
70
71 · Speaking of which, "as_code" prepends an appropriate "#line" if
72 possible, so you can single-step through your POD (yow!).
73
74 The Pod-Snippets CPAN distribution consists of a single Perl file, and
75 has no dependencies besides what comes with a standard Perl 5.8.x. It
76 is therefore easy to embed into your own module so that your users
77 won't need to install Pod::Snippets by themselves before running your
78 test suite. All that remains to do is to select the right options to
79 pass to "load" as part of an appropriately named wrapper function in
80 your test library.
81
82 Snippet Syntax
83 Pod::Snippets only deals with verbatim portions of the POD (that is, as
84 per perlpod, paragraphs that start with whitespace at the right) and
85 custom markup starting with "=for test", "=begin test" or "=end test";
86 it discards the rest (block text, actual Perl code, character markup
87 such as B<>, =head's and so on). The keyword "test" in "=for test" and
88 "=begin test" can be replaced with whatever one wants, using the
89 "-markup" argument to "load". Actually the default value is not even
90 "test"; nonetheless let's assume you are using "test" yourself for the
91 remainder of this discussion. The following metadata markup is
92 recognized:
93
94 =for test ignore
95 Starts ignoring all POD whatsoever. Verbatim portions of the POD
96 are no longer stashed by Pod::Snippets until remanded by a
97 subsequent "=for test".
98
99 =for test
100 Cancels the effect of an ongoing "=for test ignore" directive.
101
102 =for test "foo" begin
103 =for test "foo" end
104 These signal the start and end of a named POD snippet, that can
105 later be fetched by name using "named". Unless countermanded by
106 appropriate parser options (see "load"), named POD snippets can
107 nest freely (even badly).
108
109 =begin test
110 =end test
111 The POD between these markers will be seen by Pod::Snippets, but
112 not by other POD formatters. Otherwise has no effect on the naming
113 or ignoring of snippets; in particular, if the contents of the
114 section is not in POD verbatim style, it still gets ignored.
115
116 =begin test "foo"
117 =end test "foo"
118 These have the exact same effect as "=for test "foo" begin" and
119 "=for test "foo" end", except that other POD formatters will not
120 see the contents of the block.
121
123 load ($source, -opt1 => $val1, ...)
124 Parses the POD from $source and returns an object of class
125 Pod::Snippets that holds the snippets found therein. $source may be
126 the name of a file, a file descriptor (glob reference) or any object
127 that has a getline method.
128
129 Available named options are:
130
131 -filename => $filename
132 The value to set for "filename", that is, the name of the file to
133 use for "#line" lines in "as_code". The default behavior is to use
134 the filename passed as the $source argument, or if it was not a
135 filename, use the string "pod snippet" instead.
136
137 -line => $line
138 The line number to start counting lines from, eg in case the
139 $source got a few lines chopped off it before being passed to load.
140 Default is 1.
141
142 -markup => $name
143 The markup (aka "format name" in perlpod) to use as the first token
144 after "=for", "=begin" or "=end" to indicate that the directive is
145 to be processed by Pod::Snippets (see "Snippet Syntax". Default is
146 "Pod::Snippets".
147
148 -report_errors => $sub
149 Invokes $sub like so to deal with warnings and errors:
150
151 $sub->($severity, $text, $file, $line);
152
153 where $severity is either "WARNING" or "ERROR". By default the
154 standard Perl "warn" in perlfunc is used.
155
156 Regardless of the number of errors, the constructor tries to load
157 the whole file; see below.
158
159 -named_snippets => "warn_impure"
160 Raises an error upon encountering this kind of construct:
161
162 =for test "foobar" begin
163
164 my $foobar = foobar();
165
166 =head1 And now something completely different...
167
168 =for test "foobar" end
169
170 In other words, only verbatim blocks may intervene between the =for
171 test "foobar" begin and =for test "foobar" end markups.
172
173 -named_snippets => "warn_multiple"
174 Raises a warning upon encountering this kind of construct:
175
176 =for test "foobar" begin
177
178 my $foobar = foobar();
179
180 =for test "foobar" end
181
182 =for test "foobar" begin
183
184 $foobar->quux_some_more();
185
186 =for test "foobar" end
187
188 -named_snippets => "warn_overlap"
189 Raises a warning if named snippets overlap in any way.
190
191 -named_snippets => "warn_bad_pairing"
192 Raises a warning if opening and closing markup for named snippets
193 is improperly paired (eg opening or closing twice, or forgetting to
194 close before the end of the file).
195
196 -named_snippets => "error_impure"
197 -named_snippets => "error_multiple"
198 -named_snippets => "error_overlap"
199 -named_snippets => "error_bad_pairing"
200 Same as the "warn_" counterparts above, but cause errors instead of
201 warnings.
202
203 -named_snippets => "ignore_impure"
204 -named_snippets => "ignore_multiple"
205 -named_snippets => "ignore_overlap"
206 -named_snippets => "ignore_bad_pairing"
207 Ignores the corresponding dubious constructs described above. The
208 default behavior is "-named_snippets => "warn_bad_pairing"" and
209 ignore the rest.
210
211 -named_snippets => "strict"
212 Equivalent to "(-named_snippets => "error_overlap", -named_snippets
213 => "error_impure", -named_snippets => "error_multiple",
214 -named_snippets => "error_bad_pairing")".
215
216 Note that the correctness of the POD to be parsed is a prerequisite; in
217 other words, Pod::Snippets won't touch the error management knobs of
218 the underlying Pod::Parser object.
219
220 Also, note that the parser strictness options such as -named_snippets
221 have no effect on the semantics; they merely alter its response
222 (ignore, warning or error) to the aforementioned dubious constructs.
223 In any case, the parser will soldier on until the end of the file
224 regardless of the number of errors seen; however, it will disallow
225 further processing of the snippets if there were any errors (see
226 "errors").
227
228 parse ($string, -opt1 => $val1, ...)
229 Same as "load", but works from a Perl string instead of a file
230 descriptor. The named options are the same as in load(), but consider
231 using "-filename" as parse() is in no position to guess it.
232
234 filename ()
235 Returns the name of the file to use for "#line" lines in "as_code".
236 The default behavior is to use the filename passed as the $source
237 argument, or if it was not a filename, use the string "pod snippet"
238 instead.
239
240 warnings ()
241 Returns the number of warnings that occured during the parsing of the
242 POD.
243
244 errors ()
245 Returns the number of errors that occured during the parsing of the
246 POD. If that number is non-zero, then all accessors described below
247 will throw an exception instead of performing.
248
249 as_data ()
250 Returns the snippets in "data" format: that is, the return value is
251 ragged to the left by suppressing a constant number of space characters
252 at the beginning of each snippet. (If tabs are present in the POD,
253 they are treated as being of infinite length; that is, the ragging
254 algorithm does not eat them or replace them with spaces.)
255
256 A snippet is defined as a series of subsequent verbatim POD paragraphs
257 with only Pod::Snippets markup, if anything, intervening in between.
258 That is, as_data(), given the following POD in input:
259
260 my $a = new The::Brain;
261
262 =begin test
263
264 # Just kidding. We can't do that, it's too dangerous.
265 $a = new Pinky;
266
267 =end test
268
269 =for test ignore
270
271 system("/sbin/reboot");
272
273 and all of a sudden, we have:
274
275 =for test
276
277 if ($a->has_enough_cookies()) {
278 $a->conquer_world();
279 }
280
281 would return (in list context)
282
283 (<<'FIRST_SNIPPET', <<'SECOND_SNIPPET');
284 my $a = new The::Brain;
285
286
287
288 # Just kidding. We can't do that, it's too dangerous.
289 $a = new Pinky;
290 FIRST_SNIPPET
291 if ($a->has_enough_cookies()) {
292 $a->conquer_world();
293 }
294 SECOND_SNIPPET
295
296 Notice how the indentation is respected snippet-by-snippet; also,
297 notice that the FIRST_SNIPPET has been padded with an appropriate
298 number of carriage returns to replace the Pod::Snippets markup, so that
299 the return value is line-synchronized with the original POD. However,
300 leading and trailing whitespace is trimmed, leaving only strings that
301 starts with a nonblank line and end with a single newline.
302
303 In scalar context, returns the blocks joined with a single newline
304 character ("\n"), thus resulting in a single piece of text where the
305 blocks are joined by exactly one empty line (and which as a whole is no
306 longer line-synchronized with the source code, of course).
307
308 as_code ()
309 Returns the snippets formatted as code, that is, like "as_data", except
310 that each block is prepended with an appropriate "#line" statement that
311 Perl can interpret to renumber lines. For instance, these statements
312 would cause Perl to Do The Right Thing if one compiles the snippets as
313 code with "eval" in perlfunc and then runs it under the Perl debugger.
314
315 named ($name)
316 Returns a clone of this Pod::Snippet object, except that it only knows
317 about the snippet (or snippets) that are named $name. In the most lax
318 settings for the parser, this means: any and all snippets where an
319 "=for test "$name" begin" (or "=begin test "$name"") had been open, but
320 not yet closed with "=for test "$name" end" (or "=end test "$name"").
321 Returns undef if no snippet named $name was seen at all.
322
324 Test::Pod::Snippets
325
327 Dominique QUATRAVAUX, "<domq@cpan.org>"
328
330 Please report any bugs or feature requests to
331 "bug-pod-snippet@rt.cpan.org", or through the web interface at
332 <http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Pod-Snippet>. I will
333 be notified, and then you'll automatically be notified of progress on
334 your bug as I make changes.
335
337 Yanick Champoux <yanick@CPAN.org> is the author of Test::Pod::Snippets
338 which grandfathers this module.
339
341 Copyright 2007 Dominique QUATRAVAUX, all rights reserved.
342
343 This program is free software; you can redistribute it and/or modify it
344 under the same terms as Perl itself.
345
346
347
348perl v5.32.0 2020-07-28 Pod::Snippets(3)