1Test::Stream::Context(3U)ser Contributed Perl DocumentatiToenst::Stream::Context(3)
2
3
4
6 Test::Stream::Context - Object to represent a testing context.
7
9 This distribution is deprecated in favor of Test2, Test2::Suite, and
10 Test2::Workflow.
11
12 See Test::Stream::Manual::ToTest2 for a conversion guide.
13
15 The context object is the primary interface for authors of testing
16 tools written with Test::Stream. The context object represents the
17 context in which a test takes place (File and Line Number), and
18 provides a quick way to generate events from that context. The context
19 object also takes care of sending events to the correct
20 Test::Stream::Hub instance.
21
23 use Test::Stream::Context qw/context release/;
24
25 sub my_ok {
26 my ($bool, $name) = @_;
27 my $ctx = context();
28 $ctx->ok($bool, $name);
29 $ctx->release; # You MUST do this!
30 return $bool;
31 }
32
33 Context objects make it easy to wrap other tools that also use context.
34 Once you grab a context, any tool you call before releasing your
35 context will inherit it:
36
37 sub wrapper {
38 my ($bool, $name) = @_;
39 my $ctx = context();
40 $ctx->diag("wrapping my_ok");
41
42 my $out = my_ok($bool, $name);
43 $ctx->release; # You MUST do this!
44 return $out;
45 }
46
47 Notice above that we are grabbing a return value, then releasing our
48 context, then returning the value. We can combine these last 3
49 statements into a single statement using the "release" function:
50
51 sub wrapper {
52 my ($bool, $name) = @_;
53 my $ctx = context();
54 $ctx->diag("wrapping my_ok");
55
56 # You must always release the context.
57 release $ctx, my_ok($bool, $name);
58 }
59
61 You MUST always release the context when done with it
62 Releasing the context tells the system you are done with it. This
63 gives it a chance to run any necessary callbacks or cleanup tasks.
64 If you forget to release the context it will be released for you
65 using a destructor, and it will give you a warning.
66
67 In general the destructor is not preferred because it does not
68 allow callbacks to run some types of code, for example you cannot
69 throw an exception from a destructor.
70
71 You MUST NOT pass context objects around
72 When you obtain a context object it is made specifically for your
73 tool and any tools nested within. If you pass a context around you
74 run the risk of polluting other tools with incorrect context
75 information.
76
77 If you are certain that you want a different tool to use the same
78 context you may pass it a snapshot. "$ctx->snapshot" will give you
79 a shallow clone of the context that is safe to pass around or
80 store.
81
82 You MUST NOT store or cache a context for later
83 As long as a context exists for a given hub, all tools that try to
84 get a context will get the existing instance. If you try to store
85 the context you will pollute other tools with incorrect context
86 information.
87
88 If you are certain that you want to save the context for later, you
89 can use a snapshot. "$ctx->snapshot" will give you a shallow clone
90 of the context that is safe to pass around or store.
91
92 "context()" has some mechanisms to protect you if you do cause a
93 context to persist beyond the scope in which it was obtained. In
94 practice you should not rely on these protections, and they are
95 fairly noisy with warnings.
96
97 You SHOULD obtain your context as soon as possible in a given tool
98 You never know what tools you call from within your own tool will
99 need a context. Obtaining the context early ensures that nested
100 tools can find the context you want them to find.
101
103 All exports are optional, you must specify subs to import. If you want
104 to import all subs use '-all'.
105
106 use Test::Stream::Context '-all';
107
108 context()
109 Usage:
110
111 $ctx = context()
112 $ctx = context(%params)
113
114 The "context()" function will always return the current context to you.
115 If there is already a context active it will be returned. If there is
116 not an active context one will be generated. When a context is
117 generated it will default to using the file and line number where the
118 currently running sub was called from.
119
120 Please see the "CRITICAL DETAILS" section for important rools about
121 what you can and acannot do with a context once it is obtained.
122
123 Note This function will throw an exception if you ignore the context
124 object it returns.
125
126 OPTIONAL PARAMETERS
127
128 All parameters to "context" are optional.
129
130 level => $int
131 If you must obtain a context in a sub deper than your entry point
132 you can use this to tell it how many EXTRA stack frames to look
133 back. If this option is not provided the default of 0 is used.
134
135 sub third_party_tool {
136 my $sub = shift;
137 ... # Does not obtain a context
138 $sub->();
139 ...
140 }
141
142 third_party_tool(sub {
143 my $ctx = context(level => 1);
144 ...
145 $ctx->release;
146 });
147
148 wrapped => $int
149 Use this if you need to write your own tool that wraps a call to
150 "context()" with the intent that it should return a context object.
151
152 sub my_context {
153 my %params = ( wrapped => 0, @_ );
154 $params{wrapped}++;
155 my $ctx = context(%params);
156 ...
157 return $ctx;
158 }
159
160 sub my_tool {
161 my $ctx = my_context();
162 ...
163 $ctx->release;
164 }
165
166 If you do not do this than tools you call that also check for a
167 context will notice that the context they grabbed was created at
168 the same stack depth, which will trigger protective measures that
169 warn you and destroy the existing context.
170
171 stack => $stack
172 Normally "context()" looks at the global hub stack initialized in
173 Test::Stream::Sync. If you are maintaining your own
174 Test::Stream::Stack instance you may pass it in to be used instead
175 of the global one.
176
177 hub => $hub
178 Use this parameter if you want to onbtain the context for a
179 specific hub instead of whatever one happens to be at the top of
180 the stack.
181
182 on_init => sub { ... }
183 This lets you provide a callback sub that will be called ONLY if
184 your call to c<context()> generated a new context. The callback
185 WILL NOT be called if "context()" is returning an existing context.
186 The only argument passed into the callback will be the context
187 object itself.
188
189 sub foo {
190 my $ctx = context(on_init => sub { 'will run' });
191
192 my $inner = sub {
193 # This callback is not run since we are getting the existing
194 # context from our parent sub.
195 my $ctx = context(on_init => sub { 'will NOT run' });
196 $ctx->release;
197 }
198 $inner->();
199
200 $ctx->release;
201 }
202
203 on_release => sub { ... }
204 This lets you provide a callback sub that will be called when the
205 context instance is released. This callback will be added to the
206 returned context even if an existing context is returned. If
207 multiple calls to context add callbacks then all will be called in
208 reverse order when the context is finally released.
209
210 sub foo {
211 my $ctx = context(on_release => sub { 'will run second' });
212
213 my $inner = sub {
214 my $ctx = context(on_release => sub { 'will run first' });
215
216 # Neither callback runs on this release
217 $ctx->release;
218 }
219 $inner->();
220
221 # Both callbacks run here.
222 $ctx->release;
223 }
224
225 release()
226 Usage:
227
228 release $ctx;
229 release $ctx, ...;
230
231 This is intended as a shortcut that lets you release your context and
232 return a value in one statement. This function will get your context,
233 and any other arguments provided. It will release your context, then
234 return everything else. If you only provide one argument it will
235 return that one argument as a scalar. If you provide multiple
236 arguments it will return them all as a list.
237
238 sub scalar_tool {
239 my $ctx = context();
240 ...
241
242 return release $ctx, 1;
243 }
244
245 sub list_tool {
246 my $ctx = context();
247 ...
248
249 return release $ctx, qw/a b c/;
250 }
251
252 This tool is most useful when you want to return the value you get from
253 calling a function that needs to see the current context:
254
255 my $ctx = context();
256 my $out = some_tool(...);
257 $ctx->release;
258 return $out;
259
260 We can combine the last 3 lines of the above like so:
261
262 my $ctx = context();
263 release $ctx, some_tool(...);
264
266 CLASS METHODS
267 Test::Stream::Context->ON_INIT(sub { ... }, ...)
268 Test::Stream::Context->ON_RELEASE(sub { ... }, ...)
269 These are GLOBAL hooks into the context tools. Every sub added via
270 ON_INIT will be called every single time a new context is
271 initialized. Every sub added via ON_RELEASE will be called every
272 single time a context is released.
273
274 Subs will receive exactly 1 argument, that is the context itself.
275 You should not call "release" on the context within your callback.
276
277 INSTANCE METHODS
278 $clone = $ctx->snapshot()
279 This will return a shallow clone of the context. The shallow clone
280 is safe to store for later.
281
282 $ctx->release()
283 This will release the context. It will also set the $ctx variable
284 to "undef" (it works regardless of what you name the variable).
285
286 $ctx->throw($message)
287 This will throw an exception reporting to the file and line number
288 of the context. This will also release the context for you.
289
290 $ctx->alert($message)
291 This will issue a warning from the file and line number of the
292 context.
293
294 $stack = $ctx->stack()
295 This will return the Test::Stream::Stack instance the context used
296 to find the current hub.
297
298 $hub = $ctx->hub()
299 This will return the Test::Stream::Hub instance the context
300 recognises as the current one to which all events should be sent.
301
302 $dbg = $ctx->debug()
303 This will return the Test::Stream::DebugInfo instance used by the
304 context.
305
306 $ctx->do_in_context(\&code, @args);
307 Sometimes you have a context that is not current, and you want
308 things to use it as the current one. In these cases you can call
309 "$ctx->do_in_context(sub { ... })". The codeblock will be run, and
310 anything inside of it that looks for a context will find the one on
311 which the method was called.
312
313 This DOES NOT effect context on other hubs, only the hub used by
314 the context will be effected.
315
316 my $ctx = ...;
317 $ctx->do_in_context(sub {
318 my $ctx = context(); # returns the $ctx the sub is called on
319 });
320
321 EVENT PRODUCTION METHODS
322 $event = $ctx->ok($bool, $name)
323 $event = $ctx->ok($bool, $name, \@diag)
324 This will create an Test::Stream::Event::Ok object for you. The
325 diagnostics array will be used on the object in the event of a
326 failure, if the test passes the diagnostics will be ignored.
327
328 $event = $ctx->note($message)
329 Send an Test::Stream::Event::Note. This event prints a message to
330 STDOUT.
331
332 $event = $ctx->diag($message)
333 Send an Test::Stream::Event::Diag. This event prints a message to
334 STDERR.
335
336 $event = $ctx->plan($max)
337 $event = $ctx->plan(0, 'SKIP', $reason)
338 This can be used to send an Test::Stream::Event::Plan event. This
339 event usually takes either a number of tests you expect to run.
340 Optionally you can set the expected count to 0 and give the 'SKIP'
341 directive with a reason to cause all tests to be skipped.
342
343 $event = $ctx->bail($reason)
344 This sends an Test::Stream::Event::Bail event. This event will
345 completely terminate all testing.
346
347 $event = $ctx->send_event($Type, %parameters)
348 This lets you build and send an event of any type. The $Type
349 argument should be the event package name with
350 "Test::Stream::Event::" left off, or a fully qualified package name
351 prefixed with a '+'. The event is returned after it is sent.
352
353 my $event = $ctx->send_event('Ok', ...);
354
355 or
356
357 my $event = $ctx->send_event('+Test::Stream::Event::Ok', ...);
358
359 $event = $ctx->build_event($Type, %parameters)
360 This is the same as "send_event()", except it builds and returns
361 the event without sending it.
362
364 There are 2 types of hooks, init hooks, and release hooks. As the names
365 suggest, these hooks are triggered when contexts are created or
366 released.
367
368 INIT HOOKS
369 These are called whenever a context is initialized. That means when a
370 new instance is created. These hooks are NOT called every time
371 something requests a context, just when a new one is created.
372
373 GLOBAL
374
375 This is how you add a global init callback. Global callbacks happen for
376 every context for any hub or stack.
377
378 Test::Stream::Context->ON_INIT(sub {
379 my $ctx = shift;
380 ...
381 });
382
383 PER HUB
384
385 This is how you add an init callback for all contexts created for a
386 given hub. These callbacks will not run for other hubs.
387
388 $hub->add_context_init(sub {
389 my $ctx = shift;
390 ...
391 });
392
393 PER CONTEXT
394
395 This is how you specify an init hook that will only run if your call to
396 "context()" generates a new context. The callback will be ignored if
397 "context()" is returning an existing context.
398
399 my $ctx = context(on_init => sub {
400 my $ctx = shift;
401 ...
402 });
403
404 RELEASE HOOKS
405 These are called whenever a context is released. That means when the
406 last reference to the instance is about to be destroyed. These hooks
407 are NOT called every time "$ctx->release" is called.
408
409 GLOBAL
410
411 This is how you add a global release callback. Global callbacks happen
412 for every context for any hub or stack.
413
414 Test::Stream::Context->ON_RELEASE(sub {
415 my $ctx = shift;
416 ...
417 });
418
419 PER HUB
420
421 This is how you add a release callback for all contexts created for a
422 given hub. These callbacks will not run for other hubs.
423
424 $hub->add_context_release(sub {
425 my $ctx = shift;
426 ...
427 });
428
429 PER CONTEXT
430
431 This is how you add release callbacks directly to a context. The
432 callback will ALWAYS be added to the context that gets returned, it
433 does not matter if a new one is generated, or if an existing one is
434 returned.
435
436 my $ctx = context(on_release => sub {
437 my $ctx = shift;
438 ...
439 });
440
442 The source code repository for Test::Stream can be found at
443 http://github.com/Test-More/Test-Stream/.
444
446 Chad Granum <exodist@cpan.org>
447
449 Chad Granum <exodist@cpan.org>
450 Kent Fredric <kentnl@cpan.org>
451
453 Copyright 2015 Chad Granum <exodist7@gmail.com>.
454
455 This program is free software; you can redistribute it and/or modify it
456 under the same terms as Perl itself.
457
458 See http://dev.perl.org/licenses/
459
460
461
462perl v5.34.0 2022-01-21 Test::Stream::Context(3)