1IO::Capture::Extended::UOsveerrvCioenwt(r3i)buted Perl DIoOc:u:mCeanpttautrieo:n:Extended::Overview(3)
2
3
4
6 IO::Capture::Extended - Extend functionality of IO::Capture
7
9 The programmer interface consists of two classes:
10
11 IO::Capture::Stdout::Extended
12 use IO::Capture::Stdout::Extended;
13
14 $capture = IO::Capture::Stdout::Extended->new();
15 $capture->start();
16 # some code that prints to STDOUT
17 $capture->stop();
18
19 # scalar context: return number of print statements with 'fox'
20 $matches = $capture->grep_print_statements('fox');
21
22 # list context: return list of print statements with 'fox'
23 @matches = $capture->grep_print_statements('fox');
24
25 # return number of print statements
26 $matches = $capture->statements;
27
28 # scalar context: return number of pattern matches
29 $regex = qr/some regular expression/;
30 $matches = $capture->matches($regex);
31
32 # list context: return list of pattern matches
33 @matches = $capture->matches($regex);
34
35 # return reference to array holding list of pattern matches
36 $matchesref = $capture->matches_ref($regex);
37
38 # scalar context: return number of 'screen' lines printed
39 $screen_lines = $capture->all_screen_lines();
40
41 # list context: return list of 'screen' lines printed
42 @all_screen_lines = $capture->all_screen_lines();
43
44 IO::Capture::Stderr::Extended
45 $capture = IO::Capture::Stderr::Extended->new();
46 $capture->start();
47 # some code that prints to STDERR
48 $capture->stop();
49
50 ... and then use all the methods defined above for
51 IO::Capture::Stdout::Extended.
52
54 IO::Capture::Extended is a distribution consisting of two classes, each
55 of which is a collection of subroutines which are useful in extending
56 the functionality of CPAN modules IO::Capture::Stdout and
57 IO::Capture::Stderr, particularly when used in a testing context such
58 as that provided by Test::Simple, Test::More or other modules built on
59 Test::Builder.
60
62 Requirements
63 IO::Capture distribution, available from CPAN
64 <http://search.cpan.org/~reynolds/IO-Capture-0.05/>. Use version 0.05
65 or later to take advantage of important bug fixes. The IO::Capture
66 distribution includes base class IO::Capture, IO::Capture::Stdout,
67 IO::Capture::Stderr and other packages. It also includes useful
68 documentation in IO::Capture::Overview.
69
70 General Comments
71 The IO::Capture::Stdout::Extended and IO::Capture::Stdout::Extended
72 methods are designed to provide return values which work nicely as
73 arguments to Test::More functions such as ok(), is() and like(). The
74 examples below illustrate that objective. Suggestions are welcome for
75 additional methods which would fulfill that objective.
76
77 Individual Methods
78 Note: Since IO::Capture::Extended is structured so as to make exactly
79 the same methods available for IO::Capture::Stdout::Extended and
80 IO::Capture::Stderr::Extended, whenver there appears below a reference
81 to, e.g., IO::Capture::Stdout::Extended::grep_print_statements(), you
82 should assume that the remarks apply equally to
83 IO::Capture::Stderr::Extended::grep_print_statements(). Wherever
84 reference is made to STDOUT, the remarks apply to STDERR as well.
85
86 grep_print_statements()
87
88 • Scalar Context
89
90 Problem: You wish to test a function that prints to STDOUT. You
91 can predict the number of "print" statements that match a pattern
92 and wish to test that prediction. (The example below is adapted
93 from IO::Capture::Overview.)
94
95 sub print_fox {
96 print "The quick brown fox jumped over ...";
97 print "garden wall";
98 print "The quick red fox jumped over ...";
99 print "garden wall";
100 }
101
102 $capture->start;
103 print_fox();
104 $capture->stop;
105 $matches = $capture->grep_print_statements('fox');
106 is($capture->grep_print_statements('fox'), 2,
107 "correct no. of print statements grepped");
108
109 Solution: Precede the function call with a call to the
110 IO::Capture::Stdout::Extended start() method and follow it with a
111 call to the stop() method. Call "grep_print_statements". Use its
112 return value as one of two arguments to Test::More::is(). Use your
113 prediction as the other argument. Add a useful comment to is().
114
115 Potential Pitfall: The number of print statements captured between
116 IO::Capture::Stdout::Extended::start() and stop() is not
117 necessarily the number of lines that would appear to be printed to
118 standard output by a given block of code. If your subroutine or
119 other code block prints partial lines -- i.e., lines lacking "\n"
120 newline characters -- the number of print statements will be
121 greater than the number of ''screen lines.'' This is illustrated
122 by the following:
123
124 sub print_fox_long {
125 print "The quick brown fox jumped over ...";
126 print "a less adept fox\n";
127 print "The quick red fox jumped over ...";
128 print "the garden wall\n";
129 }
130
131 $capture->start;
132 print_fox_long();
133 $capture->stop;
134 $matches = $capture->grep_print_statements("fox");
135 is($capture->grep_print_statements("fox"), 3,
136 "correct no. of print statements grepped");
137
138 The number of "print" statements matching "fox" is three -- even
139 though the number of lines on the screen which appear on STDOUT
140 containing "fox" is only two.
141
142 • List Context
143
144 Problem: As above, you wish to test a function that prints to
145 STDOUT. This time, you can predict the content of "print"
146 statements that match a pattern and wish to test that prediction.
147
148 %matches = map { $_, 1 } $capture->grep_print_statements('fox');
149 is(keys %matches, 2, "correct no. of print statements grepped");
150 ok($matches{'The quick brown fox jumped over ...'},
151 'print statement correctly grepped');
152 ok($matches{'The quick red fox jumped over ...'},
153 'print statement correctly grepped');
154
155 Solution: As above, call "grep_print_statements", but map its
156 output to a 'seen-hash'. You can then use the number of keys in
157 that seen-hash as an argument to Test::More::is(). You can use
158 ok() to test whether the keys of that hash are as predicted.
159
160 statements()
161
162 Problem: You've written a function which prints to STDOUT. You can
163 make a prediction as to the number of screen lines which should be
164 printed. You want to test that prediction with Test::More::is().
165
166 sub print_greek {
167 local $_;
168 print "$_\n" for (qw| alpha beta gamma delta |);
169 }
170
171 $capture->start();
172 print_greek();
173 $capture->stop();
174 is($capture->statements, 4,
175 "number of print statements is correct");
176
177 Solution: Precede the function call with a call to the
178 IO::Capture::Stdout start() method and follow it with a call to the
179 stop() method. Call IO::Capture::Stdout::Extended::statements() and
180 use its return value as the first argument to is(). Use your
181 prediction as the second argument to is(). Be sure to write a useful
182 comment for your test.
183
184 Potential Pitfall: The number of print statements returned by
185 "statements" is not necessarily the number of lines that would appear
186 to be printed to standard output by a given block of code. If your
187 subroutine or other code block prints partial lines -- i.e., lines
188 lacking "\n" newline characters -- the number of print statements will
189 be greater than the number of ''screen lines.'' This is illustrated by
190 the following:
191
192 sub print_greek_long {
193 local $_;
194 for (qw| alpha beta gamma delta |) {
195 print $_;
196 print "\n";
197 }
198 }
199
200 $capture->start();
201 print_greek_long();
202 $capture->stop();
203 is($capture->statements, 8,
204 "number of print statements is correct");
205
206 This pitfall can be avoided by using all_screen_lines() below.
207
208 all_screen_lines()
209
210 • Scalar Context
211
212 Returns the number of lines which would normally be counted by eye
213 on STDOUT. This number is not necessarily equal to the number of
214 print() statements found in the captured output. This method
215 avoids the 'pitfall' found when using statements() above.
216
217 $capture->start();
218 print_greek_long();
219 $capture->stop();
220 $screen_lines = $capture->all_screen_lines;
221 is($screen_lines, 4, "correct no. of lines printed to screen");
222
223 • List Context
224
225 Returns an array holding lines as normally viewed on STDOUT. The
226 size of this array is not necessarily equal to the number of
227 print() statements found in the captured output. This method
228 avoids the 'pitfall' found when using statements() above.
229
230 $capture->start();
231 print_greek_long();
232 $capture->stop();
233 @all_screen_lines = $capture->all_screen_lines;
234 is($all_screen_lines[0],
235 "alpha",
236 "line correctly printed to screen");
237 is($all_screen_lines[1],
238 "beta",
239 "line correctly printed to screen");
240
241 Any newline ("\n") appearing at the end of a screen line is not
242 included in the list of lines returned by this method, i.e., the
243 lines are chomped.
244
245 matches()
246
247 • Scalar Context
248
249 Problem: You've written a function which, much like the ''mail
250 merge'' function in word processing programs, extracts data from
251 some data source, merges the data with text in a standard form, and
252 prints the result to STDOUT. You make a prediction as to the
253 number of forms which are printed to STDOUT and wish to confirm
254 that prediction.
255
256 my @week = (
257 [ qw| Monday Lundi Lunes | ],
258 [ qw| Tuesday Mardi Martes | ],
259 [ qw| Wednesday Mercredi Miercoles | ],
260 [ qw| Thursday Jeudi Jueves | ],
261 [ qw| Friday Vendredi Viernes | ],
262 [ qw| Saturday Samedi Sabado | ],
263 [ qw| Sunday Dimanche Domingo | ],
264 );
265
266 sub print_week {
267 my $weekref = shift;
268 my @week = @{$weekref};
269 for (my $day=0; $day<=$#week; $day++) {
270 print "English: $week[$day][0]\n";
271 print "French: $week[$day][1]\n";
272 print "Spanish: $week[$day][2]\n";
273 print "\n";
274 }
275 }
276
277 $capture->start();
278 print_week(\@week);
279 $capture->stop();
280 $regex = qr/English:.*?French:.*?Spanish:/s;
281
282 is($capture->matches($regex), 7,
283 "correct number of forms printed to screen");
284
285 Solution: Precede the function call with a call to the
286 IO::Capture::Stdout start() method and follow it with a call to the
287 stop() method. Write a Perl regular expression and assign it to a
288 variable using the "qr//" notation. (Remember to use the "/s"
289 modifier if the text you are testing crosses screen lines.) Pass
290 the regex variable to IO::Capture::Stdout::Extended::matches() and
291 use the return value of that method call as one argument to
292 Test::More::is(). Use your prediction as the second argument to
293 is(). Be sure to write a useful comment for your test.
294
295 • List Context
296
297 Problem: As above, you've written a function which, much like the
298 ''mail merge'' function in word processing programs, extracts data
299 from some data source, merges the data with text in a standard
300 form, and prints the result to STDOUT. This time, however, you
301 wish to do a quick test on the results by examining a sample form.
302
303 $capture->start();
304 print_week(\@week); # as defined above
305 $capture->stop();
306
307 @matches = $capture->matches($regex);
308 $predicted = "English: Monday\nFrench: Lundi\nSpanish:";
309 is($matches[0], $predicted, "first form matches test portion");
310
311 Solution: Same as above, but capture the output of matches() in a
312 list or array. Write a string which predicts typical contents of
313 one instance of your merged form. Use the contents of one form (one
314 element in the list output) and the prediction string as arguments
315 to is(). Be sure to write a useful comment for your test.
316
317 Problem: As above, but now you wish to make sure that a form was
318 generated for each required field in the data source.
319
320 $regex = qr/French:\s+(.*?)\n/s;
321 @predicted = qw| Lundi Mardi Mercredi Jeudi
322 Vendredi Samedi Dimanche |;
323 ok(eq_array( [ $capture->matches($regex) ], \@predicted ),
324 "all predicted matches found");
325
326 Solution: Similar to above, but this time you predict which data
327 points are going to be present in the output. Store that
328 prediction in a list or array. Take references to (a) the array
329 holding that prediction; and (b) the result of
330 "$capture-"matches($regex)>. Pass those two references to
331 Test::More's utility function "eq_array", which will return a true
332 value if the underlying arrays are identical element-by-element.
333 Pass that value in turn to <ok()>. As always, be sure to write a
334 useful comment for your test.
335
336 matches_ref()
337
338 Problem: Same as the first ''List Context'' example above, but now you
339 would prefer to work with a method that returns an array reference
340 rather than all the elements in a list.
341
342 $matchesref = $capture->matches_ref($regex);
343 is(${$matchesref}[0], $predicted, "first form matches test portion");
344
345 Solution: Call IO::Capture::Stdout::Extended::matches_ref() instead of
346 "matches". You will have to rephrase your test in terms of an element
347 of a dereferenced array.
348
350 As Paul Johnson says, ''Did I mention that this is alpha code?''.
351
353 Contact the author or post to the perl-qa mailing list.
354
356 Thanks go first and foremost to the two authors of the IO::Capture
357 distribution, Mark Reynolds and Jon Morgan. Mark Reynolds was
358 responsive to this module's author's suggestions for bug fixes and
359 additional tests. The documentation found in IO::Capture::Overview was
360 particularly helpful in showing me how to extend IO::Capture's
361 functionality. This distribution is maintained independently but will
362 be updated as needed if and when IO::Capture is revised.
363
364 The methods in IO::Capture::Extended are offered to the Perl community
365 in gratitude for being turned on to IO::Capture by David Cantrell on
366 the perl.qa mailing list in February 2005
367 (<http://www.nntp.perl.org/group/perl.qa/3567>).
368
369 Other contributors to that discussion thread whose suggestions are
370 reflected in this module were David H. Adler, David Golden, Michael G.
371 Schwern and Tels. Fergal Daly also made suggestions in separate
372 communications.
373
374 The structure for this module was created with my own hacked-up version
375 of R. Geoffrey Avery's modulemaker utility, based on his CPAN module
376 ExtUtils::ModuleMaker.
377
379 James E Keenan. CPAN ID: JKEENAN. jkeenan [at] cpan [dot] org.
380
382 Copyright 2005-15 James E Keenan.
383
384 This program is free software; you can redistribute it and/or modify it
385 under the same terms as Perl itself.
386
387 The full text of the license can be found in the LICENSE file included
388 with this module.
389
391 perl(1). IO::Capture; IO::Capture::Stdout; IO::Capture::Overview.
392 Test::Simple; Test::More.
393
394
395
396perl v5.38.0 2023-07-20IO::Capture::Extended::Overview(3)