1ct_hooks(3) Erlang Module Definition ct_hooks(3)
2
3
4
6 ct_hooks - A callback interface on top of Common Test.
7
9 The Common Test Hook (CTH) framework allows extensions of the default
10 behavior of Common Test by callbacks before and after all test suite
11 calls. It is intended for advanced users of Common Test who want to ab‐
12 stract out behavior that is common to multiple test suites.
13
14 In brief, CTH allows you to:
15
16 * Manipulate the runtime configuration before each suite configura‐
17 tion call.
18
19 * Manipulate the return of all suite configuration calls and by ex‐
20 tension the result of the test themselves.
21
22 The following sections describe the mandatory and optional CTH func‐
23 tions that Common Test calls during test execution. For more details,
24 see section Common Test Hooks in the User's Guide.
25
26 For information about how to add a CTH to your suite, see section In‐
27 stalling a CTH in the User's Guide.
28
29 Note:
30 For a minimal example of a CTH, see section Example CTH in the User's
31 Guide.
32
33
35 The following functions define the callback interface for a CTH.
36
38 Module:init(Id, Opts) -> {ok, State} | {ok, State, Priority}
39
40 Types:
41
42 Id = reference() | term()
43 Opts = term()
44 State = term()
45 Priority = integer()
46
47 MANDATORY
48
49 This function is always called before any other callback func‐
50 tion. Use it to initiate any common state. It is to return a
51 state for this CTH.
52
53 Id is either the return value of ct_hooks:id/1, or a reference
54 (created using erlang:make_ref/0 in ERTS) if ct_hooks:id/1 is
55 not implemented.
56
57 Priority is the relative priority of this hook. Hooks with a
58 lower priority are executed first. If no priority is specified,
59 it is set to 0.
60
61 For details about hook execution order, see section CTH Execu‐
62 tion Order in the User's Guide.
63
64 For details about when init is called, see section CTH Scope in
65 the User's Guide.
66
67 Module:post_groups(SuiteName, GroupDefs) -> NewGroupDefs
68
69 Types:
70
71 SuiteName = atom()
72 GroupDefs = NewGroupDefs = [Group]
73 Group = {GroupName,Properties,GroupsAndTestCases}
74 GroupName = atom()
75 Properties = [parallel | sequence | Shuffle | {GroupRepeat‐
76 Type,N}]
77 GroupsAndTestCases = [Group | {group,GroupName} | TestCase |
78 {testcase,TestCase,TCRepeatProps}]
79 TestCase = atom()
80 TCRepeatProps = [{repeat,N} | {repeat_until_ok,N} | {re‐
81 peat_until_fail,N}]
82 Shuffle = shuffle | {shuffle,Seed}
83 Seed = {integer(),integer(),integer()}
84 GroupRepeatType = repeat | repeat_until_all_ok | repeat_un‐
85 til_all_fail | repeat_until_any_ok | repeat_until_any_fail
86 N = integer() | forever
87
88 OPTIONAL
89
90 This function is called after groups/0. It is used to modify the
91 test group definitions, for instance to add or remove groups or
92 change group properties.
93
94 GroupDefs is what groups/0 returned, that is, a list of group
95 definitions.
96
97 NewGroupDefs is the possibly modified version of this list.
98
99 This function is called only if the CTH is added before
100 init_per_suite is run. For details, see section CTH Scope in the
101 User's Guide.
102
103 Notice that for CTHs that are installed by means of the suite/0
104 function, post_groups/2 is called before the init/2 hook func‐
105 tion. However, for CTHs that are installed by means of the CT
106 start flag, the init/2 function is called first.
107
108 Note:
109 Prior to each test execution, Common Test does a simulated test
110 run in order to count test suites, groups and cases for logging
111 purposes. This causes the post_groups/2 hook function to always
112 be called twice. For this reason, side effects are best avoided
113 in this callback.
114
115
116 Module:post_all(SuiteName, Return, GroupDefs) -> NewReturn
117
118 Types:
119
120 SuiteName = atom()
121 Return = NewReturn = Tests | {skip,Reason}
122 Tests = [TestCase | {testcase,TestCase,TCRepeatProps} |
123 {group,GroupName} | {group,GroupName,Properties} |
124 {group,GroupName,Properties,SubGroups}]
125 TestCase = atom()
126 TCRepeatProps = [{repeat,N} | {repeat_until_ok,N} | {re‐
127 peat_until_fail,N}]
128 GroupName = atom()
129 Properties = GroupProperties | default
130 SubGroups = [{GroupName,Properties} | {GroupName,Proper‐
131 ties,SubGroups}]
132 Shuffle = shuffle | {shuffle,Seed}
133 Seed = {integer(),integer(),integer()}
134 GroupRepeatType = repeat | repeat_until_all_ok | repeat_un‐
135 til_all_fail | repeat_until_any_ok | repeat_until_any_fail
136 N = integer() | forever
137 GroupDefs = NewGroupDefs = [Group]
138 Group = {GroupName,GroupProperties,GroupsAndTestCases}
139 GroupProperties = [parallel | sequence | Shuffle | {GroupRe‐
140 peatType,N}]
141 GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
142 Reason = term()
143
144 OPTIONAL
145
146 This function is called after all/0. It is used to modify the
147 set of test cases and test group to be executed, for instance to
148 add or remove test cases and groups, change group properties, or
149 even skip all tests in the suite.
150
151 Return is what all/0 returned, that is, a list of test cases and
152 groups to be executed, or a tuple {skip,Reason}.
153
154 GroupDefs is what groups/0 or the post_groups/2 hook returned,
155 that is, a list of group definitions.
156
157 NewReturn is the possibly modified version of Return.
158
159 This function is called only if the CTH is added before
160 init_per_suite is run. For details, see section CTH Scope in the
161 User's Guide.
162
163 Notice that for CTHs that are installed by means of the suite/0
164 function, post_all/2 is called before the init/2 hook function.
165 However, for CTHs that are installed by means of the CT start
166 flag, the init/2 function is called first.
167
168 Note:
169 Prior to each test execution, Common Test does a simulated test
170 run in order to count test suites, groups and cases for logging
171 purposes. This causes the post_all/3 hook function to always be
172 called twice. For this reason, side effects are best avoided in
173 this callback.
174
175
176 Module:pre_init_per_suite(SuiteName, InitData, CTHState) -> Result
177
178 Types:
179
180 SuiteName = atom()
181 InitData = Config | SkipOrFail
182 Config = NewConfig = [{Key,Value}]
183 CTHState = NewCTHState = term()
184 Result = {Return, NewCTHState}
185 Return = NewConfig | SkipOrFail
186 SkipOrFail = {fail, Reason} | {skip, Reason}
187 Key = atom()
188 Value = term()
189 Reason = term()
190
191 OPTIONAL
192
193 This function is called before init_per_suite if it exists. It
194 typically contains initialization/logging that must be done be‐
195 fore init_per_suite is called. If {skip,Reason} or {fail,Reason}
196 is returned, init_per_suite and all test cases of the suite are
197 skipped and Reason printed in the overview log of the suite.
198
199 SuiteName is the name of the suite to be run.
200
201 InitData is the original configuration list of the test suite,
202 or a SkipOrFail tuple if a previous CTH has returned this.
203
204 CTHState is the current internal state of the CTH.
205
206 Return is the result of the init_per_suite function. If it is
207 {skip,Reason} or {fail,Reason}, init_per_suite is never called,
208 instead the initiation is considered to be skipped or failed,
209 respectively. If a NewConfig list is returned, init_per_suite is
210 called with that NewConfig list. For more details, see section
211 Pre Hooks in the User's Guide.
212
213 This function is called only if the CTH is added before
214 init_per_suite is run. For details, see section CTH Scope in the
215 User's Guide.
216
217 Module:post_init_per_suite(SuiteName, Config, Return, CTHState) -> Re‐
218 sult
219
220 Types:
221
222 SuiteName = atom()
223 Config = [{Key,Value}]
224 Return = NewReturn = Config | SkipOrFail | term()
225 SkipOrFail = {fail, Reason} | {skip, Reason} | term()
226 CTHState = NewCTHState = term()
227 Result = {NewReturn, NewCTHState}
228 Key = atom()
229 Value = term()
230 Reason = term()
231
232 OPTIONAL
233
234 This function is called after init_per_suite if it exists. It
235 typically contains extra checks to ensure that all the correct
236 dependencies are started correctly.
237
238 Return is what init_per_suite returned, that is, {fail,Reason},
239 {skip,Reason}, a Config list, or a term describing how
240 init_per_suite failed.
241
242 NewReturn is the possibly modified return value of
243 init_per_suite. To recover from a failure in init_per_suite, re‐
244 turn ConfigList with the tc_status element removed. For more de‐
245 tails, see Post Hooks in section "Manipulating Tests" in the
246 User's Guide.
247
248 CTHState is the current internal state of the CTH.
249
250 This function is called only if the CTH is added before or in
251 init_per_suite. For details, see section CTH Scope in the User's
252 Guide.
253
254 Module:pre_init_per_group(SuiteName, GroupName, InitData, CTHState) ->
255 Result
256
257 Types:
258
259 SuiteName = atom()
260 GroupName = atom()
261 InitData = Config | SkipOrFail
262 Config = NewConfig = [{Key,Value}]
263 CTHState = NewCTHState = term()
264 Result = {NewConfig | SkipOrFail, NewCTHState}
265 SkipOrFail = {fail,Reason} | {skip, Reason}
266 Key = atom()
267 Value = term()
268 Reason = term()
269
270 OPTIONAL
271
272 This function is called before init_per_group if it exists. It
273 behaves the same way as pre_init_per_suite, but for function
274 init_per_group instead.
275
276 If Module:pre_init_per_group/4 is not exported, common_test will
277 attempt to call Module:pre_init_per_group(GroupName, InitData,
278 CTHState) instead. This is for backwards compatibility.
279
280 Module:post_init_per_group(SuiteName, GroupName, Config, Return, CTH‐
281 State) -> Result
282
283 Types:
284
285 SuiteName = atom()
286 GroupName = atom()
287 Config = [{Key,Value}]
288 Return = NewReturn = Config | SkipOrFail | term()
289 SkipOrFail = {fail,Reason} | {skip, Reason}
290 CTHState = NewCTHState = term()
291 Result = {NewReturn, NewCTHState}
292 Key = atom()
293 Value = term()
294 Reason = term()
295
296 OPTIONAL
297
298 This function is called after init_per_group if it exists. It
299 behaves the same way as post_init_per_suite, but for function
300 init_per_group instead.
301
302 If Module:post_init_per_group/5 is not exported, common_test
303 will attempt to call Module:post_init_per_group(GroupName, Con‐
304 fig, Return, CTHState) instead. This is for backwards compati‐
305 bility.
306
307 Module:pre_init_per_testcase(SuiteName, TestcaseName, InitData, CTH‐
308 State) -> Result
309
310 Types:
311
312 SuiteName = atom()
313 TestcaseName = atom()
314 InitData = Config | SkipOrFail
315 Config = NewConfig = [{Key,Value}]
316 CTHState = NewCTHState = term()
317 Result = {NewConfig | SkipOrFail, NewCTHState}
318 SkipOrFail = {fail,Reason} | {skip, Reason}
319 Key = atom()
320 Value = term()
321 Reason = term()
322
323 OPTIONAL
324
325 This function is called before init_per_testcase if it exists.
326 It behaves the same way as pre_init_per_suite, but for function
327 init_per_testcase instead.
328
329 If Module:pre_init_per_testcase/4 is not exported, common_test
330 will attempt to call Module:pre_init_per_testcase(TestcaseName,
331 InitData, CTHState) instead. This is for backwards compatibil‐
332 ity.
333
334 CTHs cannot be added here right now. That feature may be added
335 in a later release, but it would right now break backwards com‐
336 patibility.
337
338 Module:post_init_per_testcase(SuiteName, TestcaseName, Config, Return,
339 CTHState) -> Result
340
341 Types:
342
343 SuiteName = atom()
344 TestcaseName = atom()
345 Config = [{Key,Value}]
346 Return = NewReturn = Config | SkipOrFail | term()
347 SkipOrFail = {fail,Reason} | {skip, Reason}
348 CTHState = NewCTHState = term()
349 Result = {NewReturn, NewCTHState}
350 Key = atom()
351 Value = term()
352 Reason = term()
353
354 OPTIONAL
355
356 This function is called after init_per_testcase if it exists. It
357 behaves the same way as post_init_per_suite, but for function
358 init_per_testcase instead.
359
360 If Module:post_init_per_testcase/5 is not exported, common_test
361 will attempt to call Module:post_init_per_testcase(TestcaseName,
362 Config, Return, CTHState) instead. This is for backwards compat‐
363 ibility.
364
365 Module:pre_end_per_testcase(SuiteName, TestcaseName, EndData, CTHState)
366 -> Result
367
368 Types:
369
370 SuiteName = atom()
371 TestcaseName = atom()
372 EndData = Config
373 Config = NewConfig = [{Key,Value}]
374 CTHState = NewCTHState = term()
375 Result = {NewConfig, NewCTHState}
376 Key = atom()
377 Value = term()
378 Reason = term()
379
380 OPTIONAL
381
382 This function is called before end_per_testcase if it exists. It
383 behaves the same way as pre_end_per_suite, but for function
384 end_per_testcase instead.
385
386 This function cannot change the result of the test case by re‐
387 turning skip or fail tuples, but it may insert items in Config
388 that can be read in end_per_testcase/2 or in post_end_per_test‐
389 case/5.
390
391 If Module:pre_end_per_testcase/4 is not exported, common_test
392 will attempt to call Module:pre_end_per_testcase(TestcaseName,
393 EndData, CTHState) instead. This is for backwards compatibility.
394
395 Module:post_end_per_testcase(SuiteName, TestcaseName, Config, Return,
396 CTHState) -> Result
397
398 Types:
399
400 SuiteName = atom()
401 TestcaseName = atom()
402 Config = [{Key,Value}]
403 Return = NewReturn = Config | SkipOrFail | term()
404 SkipOrFail = {fail,Reason} | {skip, Reason}
405 CTHState = NewCTHState = term()
406 Result = {NewReturn, NewCTHState}
407 Key = atom()
408 Value = term()
409 Reason = term()
410
411 OPTIONAL
412
413 This function is called after end_per_testcase if it exists. It
414 behaves the same way as post_end_per_suite, but for function
415 end_per_testcase instead.
416
417 If Module:post_end_per_testcase/5 is not exported, common_test
418 will attempt to call Module:post_end_per_testcase(TestcaseName,
419 Config, Return, CTHState) instead. This is for backwards compat‐
420 ibility.
421
422 Module:pre_end_per_group(SuiteName, GroupName, EndData, CTHState) ->
423 Result
424
425 Types:
426
427 SuiteName = atom()
428 GroupName = atom()
429 EndData = Config | SkipOrFail
430 Config = NewConfig = [{Key,Value}]
431 CTHState = NewCTHState = term()
432 Result = {NewConfig | SkipOrFail, NewCTHState}
433 SkipOrFail = {fail,Reason} | {skip, Reason}
434 Key = atom()
435 Value = term()
436 Reason = term()
437
438 OPTIONAL
439
440 This function is called before end_per_group if it exists. It
441 behaves the same way as pre_init_per_suite, but for function
442 end_per_group instead.
443
444 If Module:pre_end_per_group/4 is not exported, common_test will
445 attempt to call Module:pre_end_per_group(GroupName, EndData,
446 CTHState) instead. This is for backwards compatibility.
447
448 Module:post_end_per_group(SuiteName, GroupName, Config, Return, CTH‐
449 State) -> Result
450
451 Types:
452
453 SuiteName = atom()
454 GroupName = atom()
455 Config = [{Key,Value}]
456 Return = NewReturn = Config | SkipOrFail | term()
457 SkipOrFail = {fail,Reason} | {skip, Reason}
458 CTHState = NewCTHState = term()
459 Result = {NewReturn, NewCTHState}
460 Key = atom()
461 Value = term()
462 Reason = term()
463
464 OPTIONAL
465
466 This function is called after end_per_group if it exists. It be‐
467 haves the same way as post_init_per_suite, but for function
468 end_per_group instead.
469
470 If Module:post_end_per_group/5 is not exported, common_test will
471 attempt to call Module:post_end_per_group(GroupName, Config, Re‐
472 turn, CTHState) instead. This is for backwards compatibility.
473
474 Module:pre_end_per_suite(SuiteName, EndData, CTHState) -> Result
475
476 Types:
477
478 SuiteName = atom()
479 EndData = Config | SkipOrFail
480 Config = NewConfig = [{Key,Value}]
481 CTHState = NewCTHState = term()
482 Result = {NewConfig | SkipOrFail, NewCTHState}
483 SkipOrFail = {fail,Reason} | {skip, Reason}
484 Key = atom()
485 Value = term()
486 Reason = term()
487
488 OPTIONAL
489
490 This function is called before end_per_suite if it exists. It
491 behaves the same way as pre_init_per_suite, but for function
492 end_per_suite instead.
493
494 Module:post_end_per_suite(SuiteName, Config, Return, CTHState) -> Re‐
495 sult
496
497 Types:
498
499 SuiteName = atom()
500 Config = [{Key,Value}]
501 Return = NewReturn = Config | SkipOrFail | term()
502 SkipOrFail = {fail,Reason} | {skip, Reason}
503 CTHState = NewCTHState = term()
504 Result = {NewReturn, NewCTHState}
505 Key = atom()
506 Value = term()
507 Reason = term()
508
509 OPTIONAL
510
511 This function is called after end_per_suite if it exists. It be‐
512 haves the same way as post_init_per_suite, but for function
513 end_per_suite instead.
514
515 Module:on_tc_fail(SuiteName, TestName, Reason, CTHState) -> NewCTHState
516
517 Types:
518
519 SuiteName = atom()
520 TestName = init_per_suite | end_per_suite |
521 {init_per_group,GroupName} | {end_per_group,GroupName} |
522 {FuncName,GroupName} | FuncName
523 FuncName = atom()
524 GroupName = atom()
525 Reason = term()
526 CTHState = NewCTHState = term()
527
528 OPTIONAL
529
530 This function is called whenever a test case (or configuration
531 function) fails. It is called after the post function is called
532 for the failed test case, that is:
533
534 * If init_per_suite fails, this function is called after
535 post_init_per_suite.
536
537 * If a test case fails, this function is called after
538 post_end_per_testcase.
539
540 If the failed test case belongs to a test case group, the first
541 argument is a tuple {FuncName,GroupName}, otherwise only the
542 function name.
543
544 The data that comes with Reason follows the same format as Fail‐
545 Reason in event tc_done. For details, see section Event Handling
546 in the User's Guide.
547
548 If Module:on_tc_fail/4 is not exported, common_test will attempt
549 to call Module:on_tc_fail(TestName, Reason, CTHState) instead.
550 This is for backwards compatibility.
551
552 Module:on_tc_skip(SuiteName, TestName, Reason, CTHState) -> NewCTHState
553
554 Types:
555
556 SuiteName = atom()
557 TestName = init_per_suite | end_per_suite |
558 {init_per_group,GroupName} | {end_per_group,GroupName} |
559 {FuncName,GroupName} | FuncName
560 FuncName = atom()
561 GroupName = atom()
562 Reason = {tc_auto_skip | tc_user_skip, term()}
563 CTHState = NewCTHState = term()
564
565 OPTIONAL
566
567 This function is called whenever a test case (or configuration
568 function) is skipped. It is called after the post function is
569 called for the skipped test case, that is:
570
571 * If init_per_group is skipped, this function is called after
572 post_init_per_group.
573
574 * If a test case is skipped, this function is called after
575 post_end_per_testcase.
576
577 If the skipped test case belongs to a test case group, the first
578 argument is a tuple {FuncName,GroupName}, otherwise only the
579 function name.
580
581 The data that comes with Reason follows the same format as
582 events tc_auto_skip and tc_user_skip For details, see section
583 Event Handling in the User's Guide.
584
585 If Module:on_tc_skip/4 is not exported, common_test will attempt
586 to call Module:on_tc_skip(TestName, Reason, CTHState) instead.
587 This is for backwards compatibility.
588
589 Module:terminate(CTHState)
590
591 Types:
592
593 CTHState = term()
594
595 OPTIONAL
596
597 This function is called at the end of a CTH scope.
598
599 Module:id(Opts) -> Id
600
601 Types:
602
603 Opts = term()
604 Id = term()
605
606 OPTIONAL
607
608 The Id identifies a CTH instance uniquely. If two CTHs return
609 the same Id, the second CTH is ignored and subsequent calls to
610 the CTH are only made to the first instance. For details, see
611 section Installing a CTH in the User's Guide.
612
613 This function is not to have any side effects, as it can be
614 called multiple times by Common Test.
615
616 If not implemented, the CTH acts as if this function returned a
617 call to make_ref/0.
618
619
620
621Ericsson AB common_test 1.25.1 ct_hooks(3)