1Test2::API::Context(3)User Contributed Perl DocumentationTest2::API::Context(3)
2
3
4
6 Test2::API::Context - Object to represent a testing context.
7
9 The context object is the primary interface for authors of testing
10 tools written with Test2. The context object represents the context in
11 which a test takes place (File and Line Number), and provides a quick
12 way to generate events from that context. The context object also takes
13 care of sending events to the correct Test2::Hub instance.
14
16 In general you will not be creating contexts directly. To obtain a
17 context you should always use "context()" which is exported by the
18 Test2::API module.
19
20 use Test2::API qw/context/;
21
22 sub my_ok {
23 my ($bool, $name) = @_;
24 my $ctx = context();
25
26 if ($bool) {
27 $ctx->pass($name);
28 }
29 else {
30 $ctx->fail($name);
31 }
32
33 $ctx->release; # You MUST do this!
34 return $bool;
35 }
36
37 Context objects make it easy to wrap other tools that also use context.
38 Once you grab a context, any tool you call before releasing your
39 context will inherit it:
40
41 sub wrapper {
42 my ($bool, $name) = @_;
43 my $ctx = context();
44 $ctx->diag("wrapping my_ok");
45
46 my $out = my_ok($bool, $name);
47 $ctx->release; # You MUST do this!
48 return $out;
49 }
50
52 you MUST always use the context() sub from Test2::API
53 Creating your own context via "Test2::API::Context->new()" will
54 almost never produce a desirable result. Use "context()" which is
55 exported by Test2::API.
56
57 There are a handful of cases where a tool author may want to create
58 a new context by hand, which is why the "new" method exists. Unless
59 you really know what you are doing you should avoid this.
60
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 try to detect the
65 problem and warn you about it.
66
67 You MUST NOT pass context objects around
68 When you obtain a context object it is made specifically for your
69 tool and any tools nested within. If you pass a context around you
70 run the risk of polluting other tools with incorrect context
71 information.
72
73 If you are certain that you want a different tool to use the same
74 context you may pass it a snapshot. "$ctx->snapshot" will give you
75 a shallow clone of the context that is safe to pass around or
76 store.
77
78 You MUST NOT store or cache a context for later
79 As long as a context exists for a given hub, all tools that try to
80 get a context will get the existing instance. If you try to store
81 the context you will pollute other tools with incorrect context
82 information.
83
84 If you are certain that you want to save the context for later, you
85 can use a snapshot. "$ctx->snapshot" will give you a shallow clone
86 of the context that is safe to pass around or store.
87
88 "context()" has some mechanisms to protect you if you do cause a
89 context to persist beyond the scope in which it was obtained. In
90 practice you should not rely on these protections, and they are
91 fairly noisy with warnings.
92
93 You SHOULD obtain your context as soon as possible in a given tool
94 You never know what tools you call from within your own tool will
95 need a context. Obtaining the context early ensures that nested
96 tools can find the context you want them to find.
97
99 $ctx->done_testing;
100 Note that testing is finished. If no plan has been set this will
101 generate a Plan event.
102
103 $clone = $ctx->snapshot()
104 This will return a shallow clone of the context. The shallow clone
105 is safe to store for later.
106
107 $ctx->release()
108 This will release the context. This runs cleanup tasks, and several
109 important hooks. It will also restore $!, $?, and $@ to what they
110 were when the context was created.
111
112 Note: If a context is acquired more than once an internal refcount
113 is kept. "release()" decrements the ref count, none of the other
114 actions of "release()" will occur unless the refcount hits 0. This
115 means only the last call to "release()" will reset $?, $!, $@,and
116 run the cleanup tasks.
117
118 $ctx->throw($message)
119 This will throw an exception reporting to the file and line number
120 of the context. This will also release the context for you.
121
122 $ctx->alert($message)
123 This will issue a warning from the file and line number of the
124 context.
125
126 $stack = $ctx->stack()
127 This will return the Test2::API::Stack instance the context used to
128 find the current hub.
129
130 $hub = $ctx->hub()
131 This will return the Test2::Hub instance the context recognizes as
132 the current one to which all events should be sent.
133
134 $dbg = $ctx->trace()
135 This will return the Test2::EventFacet::Trace instance used by the
136 context.
137
138 $ctx->do_in_context(\&code, @args);
139 Sometimes you have a context that is not current, and you want
140 things to use it as the current one. In these cases you can call
141 "$ctx->do_in_context(sub { ... })". The codeblock will be run, and
142 anything inside of it that looks for a context will find the one on
143 which the method was called.
144
145 This DOES NOT affect context on other hubs, only the hub used by
146 the context will be affected.
147
148 my $ctx = ...;
149 $ctx->do_in_context(sub {
150 my $ctx = context(); # returns the $ctx the sub is called on
151 });
152
153 Note: The context will actually be cloned, the clone will be used
154 instead of the original. This allows the thread id, process id, and
155 error variables to be correct without modifying the original
156 context.
157
158 $ctx->restore_error_vars()
159 This will set $!, $?, and $@ to what they were when the context was
160 created. There is no localization or anything done here, calling
161 this method will actually set these vars.
162
163 $! = $ctx->errno()
164 The (numeric) value of $! when the context was created.
165
166 $? = $ctx->child_error()
167 The value of $? when the context was created.
168
169 $@ = $ctx->eval_error()
170 The value of $@ when the context was created.
171
172 EVENT PRODUCTION METHODS
173 Which one do I use?
174
175 The "pass*" and "fail*" are optimal if they meet your situation, using
176 one of them will always be the most optimal. That said they are optimal
177 by eliminating many features.
178
179 Method such as "ok", and "note" are shortcuts for generating common
180 1-task events based on the old API, however they are forward
181 compatible, and easy to use. If these meet your needs then go ahead and
182 use them, but please check back often for alternatives that may be
183 added.
184
185 If you want to generate new style events, events that do many things at
186 once, then you want the "*ev2*" methods. These let you directly specify
187 which facets you wish to use.
188
189 $event = $ctx->pass()
190 $event = $ctx->pass($name)
191 This will send and return an Test2::Event::Pass event. You may
192 optionally provide a $name for the assertion.
193
194 The Test2::Event::Pass is a specially crafted and optimized event,
195 using this will help the performance of passing tests.
196
197 $true = $ctx->pass_and_release()
198 $true = $ctx->pass_and_release($name)
199 This is a combination of "pass()" and "release()". You can use this
200 if you do not plan to do anything with the context after sending
201 the event. This helps write more clear and compact code.
202
203 sub shorthand {
204 my ($bool, $name) = @_;
205 my $ctx = context();
206 return $ctx->pass_and_release($name) if $bool;
207
208 ... Handle a failure ...
209 }
210
211 sub longform {
212 my ($bool, $name) = @_;
213 my $ctx = context();
214
215 if ($bool) {
216 $ctx->pass($name);
217 $ctx->release;
218 return 1;
219 }
220
221 ... Handle a failure ...
222 }
223
224 my $event = $ctx->fail()
225 my $event = $ctx->fail($name)
226 my $event = $ctx->fail($name, @diagnostics)
227 This lets you send an Test2::Event::Fail event. You may optionally
228 provide a $name and @diagnostics messages.
229
230 Diagnostics messages can be simple strings, data structures, or
231 instances of Test2::EventFacet::Info::Table (which are converted
232 inline into the Test2::EventFacet::Info structure).
233
234 my $false = $ctx->fail_and_release()
235 my $false = $ctx->fail_and_release($name)
236 my $false = $ctx->fail_and_release($name, @diagnostics)
237 This is a combination of "fail()" and "release()". This can be used
238 to write clearer and shorter code.
239
240 sub shorthand {
241 my ($bool, $name) = @_;
242 my $ctx = context();
243 return $ctx->fail_and_release($name) unless $bool;
244
245 ... Handle a success ...
246 }
247
248 sub longform {
249 my ($bool, $name) = @_;
250 my $ctx = context();
251
252 unless ($bool) {
253 $ctx->pass($name);
254 $ctx->release;
255 return 1;
256 }
257
258 ... Handle a success ...
259 }
260
261 $event = $ctx->ok($bool, $name)
262 $event = $ctx->ok($bool, $name, \@on_fail)
263 NOTE: Use of this method is discouraged in favor of "pass()" and
264 "fail()" which produce Test2::Event::Pass and Test2::Event::Fail
265 events. These newer event types are faster and less crufty.
266
267 This will create an Test2::Event::Ok object for you. If $bool is
268 false then an Test2::Event::Diag event will be sent as well with
269 details about the failure. If you do not want automatic diagnostics
270 you should use the "send_event()" method directly.
271
272 The third argument "\@on_fail") is an optional set of diagnostics
273 to be sent in the event of a test failure. Unlike with "fail()"
274 these diagnostics must be plain strings, data structures are not
275 supported.
276
277 $event = $ctx->note($message)
278 Send an Test2::Event::Note. This event prints a message to STDOUT.
279
280 $event = $ctx->diag($message)
281 Send an Test2::Event::Diag. This event prints a message to STDERR.
282
283 $event = $ctx->plan($max)
284 $event = $ctx->plan(0, 'SKIP', $reason)
285 This can be used to send an Test2::Event::Plan event. This event
286 usually takes either a number of tests you expect to run.
287 Optionally you can set the expected count to 0 and give the 'SKIP'
288 directive with a reason to cause all tests to be skipped.
289
290 $event = $ctx->skip($name, $reason);
291 Send an Test2::Event::Skip event.
292
293 $event = $ctx->bail($reason)
294 This sends an Test2::Event::Bail event. This event will completely
295 terminate all testing.
296
297 $event = $ctx->send_ev2(%facets)
298 This lets you build and send a V2 event directly from facets. The
299 event is returned after it is sent.
300
301 This example sends a single assertion, a note (comment for stdout
302 in Test::Builder talk) and sets the plan to 1.
303
304 my $event = $ctx->send_event(
305 plan => {count => 1},
306 assert => {pass => 1, details => "A passing assert"},
307 info => [{tag => 'NOTE', details => "This is a note"}],
308 );
309
310 $event = $ctx->build_e2(%facets)
311 This is the same as "send_ev2()", except it builds and returns the
312 event without sending it.
313
314 $event = $ctx->send_ev2_and_release($Type, %parameters)
315 This is a combination of "send_ev2()" and "release()".
316
317 sub shorthand {
318 my $ctx = context();
319 return $ctx->send_ev2_and_release(assert => {pass => 1, details => 'foo'});
320 }
321
322 sub longform {
323 my $ctx = context();
324 my $event = $ctx->send_ev2(assert => {pass => 1, details => 'foo'});
325 $ctx->release;
326 return $event;
327 }
328
329 $event = $ctx->send_event($Type, %parameters)
330 It is better to use send_ev2() in new code.
331
332 This lets you build and send an event of any type. The $Type
333 argument should be the event package name with "Test2::Event::"
334 left off, or a fully qualified package name prefixed with a '+'.
335 The event is returned after it is sent.
336
337 my $event = $ctx->send_event('Ok', ...);
338
339 or
340
341 my $event = $ctx->send_event('+Test2::Event::Ok', ...);
342
343 $event = $ctx->build_event($Type, %parameters)
344 It is better to use build_ev2() in new code.
345
346 This is the same as "send_event()", except it builds and returns
347 the event without sending it.
348
349 $event = $ctx->send_event_and_release($Type, %parameters)
350 It is better to use send_ev2_and_release() in new code.
351
352 This is a combination of "send_event()" and "release()".
353
354 sub shorthand {
355 my $ctx = context();
356 return $ctx->send_event_and_release(Pass => { name => 'foo' });
357 }
358
359 sub longform {
360 my $ctx = context();
361 my $event = $ctx->send_event(Pass => { name => 'foo' });
362 $ctx->release;
363 return $event;
364 }
365
367 There are 2 types of hooks, init hooks, and release hooks. As the names
368 suggest, these hooks are triggered when contexts are created or
369 released.
370
371 INIT HOOKS
372 These are called whenever a context is initialized. That means when a
373 new instance is created. These hooks are NOT called every time
374 something requests a context, just when a new one is created.
375
376 GLOBAL
377
378 This is how you add a global init callback. Global callbacks happen for
379 every context for any hub or stack.
380
381 Test2::API::test2_add_callback_context_init(sub {
382 my $ctx = shift;
383 ...
384 });
385
386 PER HUB
387
388 This is how you add an init callback for all contexts created for a
389 given hub. These callbacks will not run for other hubs.
390
391 $hub->add_context_init(sub {
392 my $ctx = shift;
393 ...
394 });
395
396 PER CONTEXT
397
398 This is how you specify an init hook that will only run if your call to
399 "context()" generates a new context. The callback will be ignored if
400 "context()" is returning an existing context.
401
402 my $ctx = context(on_init => sub {
403 my $ctx = shift;
404 ...
405 });
406
407 RELEASE HOOKS
408 These are called whenever a context is released. That means when the
409 last reference to the instance is about to be destroyed. These hooks
410 are NOT called every time "$ctx->release" is called.
411
412 GLOBAL
413
414 This is how you add a global release callback. Global callbacks happen
415 for every context for any hub or stack.
416
417 Test2::API::test2_add_callback_context_release(sub {
418 my $ctx = shift;
419 ...
420 });
421
422 PER HUB
423
424 This is how you add a release callback for all contexts created for a
425 given hub. These callbacks will not run for other hubs.
426
427 $hub->add_context_release(sub {
428 my $ctx = shift;
429 ...
430 });
431
432 PER CONTEXT
433
434 This is how you add release callbacks directly to a context. The
435 callback will ALWAYS be added to the context that gets returned, it
436 does not matter if a new one is generated, or if an existing one is
437 returned.
438
439 my $ctx = context(on_release => sub {
440 my $ctx = shift;
441 ...
442 });
443
445 This object consumes Test2::Util::ExternalMeta which provides a
446 consistent way for you to attach meta-data to instances of this class.
447 This is useful for tools, plugins, and other extensions.
448
450 The source code repository for Test2 can be found at
451 http://github.com/Test-More/test-more/.
452
454 Chad Granum <exodist@cpan.org>
455
457 Chad Granum <exodist@cpan.org>
458 Kent Fredric <kentnl@cpan.org>
459
461 Copyright 2019 Chad Granum <exodist@cpan.org>.
462
463 This program is free software; you can redistribute it and/or modify it
464 under the same terms as Perl itself.
465
466 See http://dev.perl.org/licenses/
467
468
469
470perl v5.30.0 2019-09-06 Test2::API::Context(3)