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