Go to main content

man pages section 3: Extended Library Functions, Volume 1

Exit Print View

Updated: Wednesday, July 27, 2022
 
 

ct_hooks (3erl)

Name

ct_hooks - A callback interface on top of Common Test.

Synopsis

Please see following description for synopsis

Description

ct_hooks(3)                Erlang Module Definition                ct_hooks(3)



NAME
       ct_hooks - A callback interface on top of Common Test.

DESCRIPTION
       The  Common  Test Hook (CTH) framework allows extensions of the default
       behavior of Common Test by callbacks before and after  all  test  suite
       calls.  It  is  intended  for advanced users of Common Test who want to
       abstract out behavior that is common to multiple test suites.

       In brief, CTH allows you to:

         * Manipulate the runtime configuration before each  suite  configura-
           tion call.

         * Manipulate  the  return  of  all  suite  configuration calls and by
           extension the result of the test themselves.

       The following sections describe the mandatory and  optional  CTH  func-
       tions  that  Common Test calls during test execution. For more details,
       see section Common Test Hooks in the User's Guide.

       For information about how to add a  CTH  to  your  suite,  see  section
       Installing a CTH in the User's Guide.

   Note:
       For  a  minimal example of a CTH, see section Example CTH in the User's
       Guide.


CALLBACK FUNCTIONS
       The following functions define the callback interface for a CTH.

EXPORTS
       Module:init(Id, Opts) -> {ok, State} | {ok, State, Priority}

              Types:

                 Id = reference() | term()
                 Opts = term()
                 State = term()
                 Priority = integer()

              MANDATORY

              This function is always called before any other  callback  func-
              tion.  Use  it  to  initiate any common state. It is to return a
              state for this CTH.

              Id is either the return value of ct_hooks:id/1, or  a  reference
              (created  using  erlang:make_ref/0  in ERTS) if ct_hooks:id/1 is
              not implemented.

              Priority is the relative priority of this  hook.  Hooks  with  a
              lower  priority are executed first. If no priority is specified,
              it is set to 0.

              For details about when init is called, see section CTH Scope  in
              the User's Guide.

       Module:post_groups(SuiteName, GroupDefs) -> NewGroupDefs

              Types:

                 SuiteName = atom()
                 GroupDefs = NewGroupDefs = [Group]
                 Group = {GroupName,Properties,GroupsAndTestCases}
                 GroupName = atom()
                 Properties  =  [parallel | sequence | Shuffle | {GroupRepeat-
                 Type,N}]
                 GroupsAndTestCases = [Group | {group,GroupName} | TestCase  |
                 {testcase,TestCase,TCRepeatProps}]
                 TestCase = atom()
                 TCRepeatProps   =   [{repeat,N}   |   {repeat_until_ok,N}   |
                 {repeat_until_fail,N}]
                 Shuffle = shuffle | {shuffle,Seed}
                 Seed = {integer(),integer(),integer()}
                 GroupRepeatType   =   repeat    |    repeat_until_all_ok    |
                 repeat_until_all_fail       |      repeat_until_any_ok      |
                 repeat_until_any_fail
                 N = integer() | forever

              OPTIONAL

              This function is called after groups/0. It is used to modify the
              test  group definitions, for instance to add or remove groups or
              change group properties.

              GroupDefs is what groups/0 returned, that is, a  list  of  group
              definitions.

              NewGroupDefs is the possibly modified version of this list.

              This  function  is  called  only  if  the  CTH  is  added before
              init_per_suite is run. For details, see section CTH Scope in the
              User's Guide.

              Notice  that for CTHs that are installed by means of the suite/0
              function, post_groups/2 is called before the init/2  hook  func-
              tion.  However,  for  CTHs that are installed by means of the CT
              start flag, the init/2 function is called first.

          Note:
              Prior to each test execution, Common Test does a simulated  test
              run  in order to count test suites, groups and cases for logging
              purposes. This causes the post_groups/2 hook function to  always
              be  called twice. For this reason, side effects are best avoided
              in this callback.


       Module:post_all(SuiteName, Return, GroupDefs) -> NewReturn

              Types:

                 SuiteName = atom()
                 Return = NewReturn = Tests | {skip,Reason}
                 Tests  =  [TestCase  |  {testcase,TestCase,TCRepeatProps}   |
                 {group,GroupName}     |     {group,GroupName,Properties}    |
                 {group,GroupName,Properties,SubGroups}]
                 TestCase = atom()
                 TCRepeatProps   =   [{repeat,N}   |   {repeat_until_ok,N}   |
                 {repeat_until_fail,N}]
                 GroupName = atom()
                 Properties = GroupProperties | default
                 SubGroups   =  [{GroupName,Properties}  |  {GroupName,Proper-
                 ties,SubGroups}]
                 Shuffle = shuffle | {shuffle,Seed}
                 Seed = {integer(),integer(),integer()}
                 GroupRepeatType   =   repeat    |    repeat_until_all_ok    |
                 repeat_until_all_fail       |      repeat_until_any_ok      |
                 repeat_until_any_fail
                 N = integer() | forever
                 GroupDefs = NewGroupDefs = [Group]
                 Group = {GroupName,GroupProperties,GroupsAndTestCases}
                 GroupProperties = [parallel | sequence | Shuffle |  {GroupRe-
                 peatType,N}]
                 GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
                 Reason = term()

              OPTIONAL

              This  function  is  called after all/0. It is used to modify the
              set of test cases and test group to be executed, for instance to
              add or remove test cases and groups, change group properties, or
              even skip all tests in the suite.

              Return is what all/0 returned, that is, a list of test cases and
              groups to be executed, or a tuple {skip,Reason}.

              GroupDefs  is  what groups/0 or the post_groups/2 hook returned,
              that is, a list of group definitions.

              NewReturn is the possibly modified version of Return.

              This function  is  called  only  if  the  CTH  is  added  before
              init_per_suite is run. For details, see section CTH Scope in the
              User's Guide.

              Notice that for CTHs that are installed by means of the  suite/0
              function,  post_all/2 is called before the init/2 hook function.
              However, for CTHs that are installed by means of  the  CT  start
              flag, the init/2 function is called first.

          Note:
              Prior  to each test execution, Common Test does a simulated test
              run in order to count test suites, groups and cases for  logging
              purposes.  This causes the post_all/3 hook function to always be
              called twice. For this reason, side effects are best avoided  in
              this callback.


       Module:pre_init_per_suite(SuiteName, InitData, CTHState) -> Result

              Types:

                 SuiteName = atom()
                 InitData = Config | SkipOrFail
                 Config = NewConfig = [{Key,Value}]
                 CTHState = NewCTHState = term()
                 Result = {Return, NewCTHState}
                 Return = NewConfig | SkipOrFail
                 SkipOrFail = {fail, Reason} | {skip, Reason}
                 Key = atom()
                 Value = term()
                 Reason = term()

              OPTIONAL

              This  function  is called before init_per_suite if it exists. It
              typically contains  initialization/logging  that  must  be  done
              before  init_per_suite is called. If {skip,Reason} or {fail,Rea-
              son} is returned, init_per_suite and all test cases of the suite
              are skipped and Reason printed in the overview log of the suite.

              SuiteName is the name of the suite to be run.

              InitData  is  the original configuration list of the test suite,
              or a SkipOrFail tuple if a previous CTH has returned this.

              CTHState is the current internal state of the CTH.

              Return is the result of the init_per_suite function.  If  it  is
              {skip,Reason}  or {fail,Reason}, init_per_suite is never called,
              instead the initiation is considered to be  skipped  or  failed,
              respectively. If a NewConfig list is returned, init_per_suite is
              called with that NewConfig list. For more details,  see  section
              Pre Hooks in the User's Guide.

              This  function  is  called  only  if  the  CTH  is  added before
              init_per_suite is run. For details, see section CTH Scope in the
              User's Guide.

       Module:post_init_per_suite(SuiteName,   Config,  Return,  CTHState)  ->
       Result

              Types:

                 SuiteName = atom()
                 Config = [{Key,Value}]
                 Return = NewReturn = Config | SkipOrFail | term()
                 SkipOrFail = {fail, Reason} | {skip, Reason} | term()
                 CTHState = NewCTHState = term()
                 Result = {NewReturn, NewCTHState}
                 Key = atom()
                 Value = term()
                 Reason = term()

              OPTIONAL

              This function is called after init_per_suite if  it  exists.  It
              typically  contains  extra checks to ensure that all the correct
              dependencies are started correctly.

              Return is what init_per_suite returned, that is,  {fail,Reason},
              {skip,Reason},   a   Config  list,  or  a  term  describing  how
              init_per_suite failed.

              NewReturn   is   the   possibly   modified   return   value   of
              init_per_suite.  To  recover  from  a failure in init_per_suite,
              return ConfigList with the tc_status element removed.  For  more
              details,  see  Post Hooks in section "Manipulating Tests" in the
              User's Guide.

              CTHState is the current internal state of the CTH.

              This function is called only if the CTH is added  before  or  in
              init_per_suite. For details, see section CTH Scope in the User's
              Guide.

       Module:pre_init_per_group(SuiteName, GroupName, InitData, CTHState)  ->
       Result

              Types:

                 SuiteName = atom()
                 GroupName = atom()
                 InitData = Config | SkipOrFail
                 Config = NewConfig = [{Key,Value}]
                 CTHState = NewCTHState = term()
                 Result = {NewConfig | SkipOrFail, NewCTHState}
                 SkipOrFail = {fail,Reason} | {skip, Reason}
                 Key = atom()
                 Value = term()
                 Reason = term()

              OPTIONAL

              This  function  is called before init_per_group if it exists. It
              behaves the same way as  pre_init_per_suite,  but  for  function
              init_per_group instead.

              If Module:pre_init_per_group/4 is not exported, common_test will
              attempt to call  Module:pre_init_per_group(GroupName,  InitData,
              CTHState) instead. This is for backwards compatibility.

       Module:post_init_per_group(SuiteName,  GroupName,  Config, Return, CTH-
       State) -> Result

              Types:

                 SuiteName = atom()
                 GroupName = atom()
                 Config = [{Key,Value}]
                 Return = NewReturn = Config | SkipOrFail | term()
                 SkipOrFail = {fail,Reason} | {skip, Reason}
                 CTHState = NewCTHState = term()
                 Result = {NewReturn, NewCTHState}
                 Key = atom()
                 Value = term()
                 Reason = term()

              OPTIONAL

              This function is called after init_per_group if  it  exists.  It
              behaves  the  same  way as post_init_per_suite, but for function
              init_per_group instead.

              If Module:post_init_per_group/5  is  not  exported,  common_test
              will  attempt to call Module:post_init_per_group(GroupName, Con-
              fig, Return, CTHState) instead. This is for  backwards  compati-
              bility.

       Module:pre_init_per_testcase(SuiteName,  TestcaseName,  InitData,  CTH-
       State) -> Result

              Types:

                 SuiteName = atom()
                 TestcaseName = atom()
                 InitData = Config | SkipOrFail
                 Config = NewConfig = [{Key,Value}]
                 CTHState = NewCTHState = term()
                 Result = {NewConfig | SkipOrFail, NewCTHState}
                 SkipOrFail = {fail,Reason} | {skip, Reason}
                 Key = atom()
                 Value = term()
                 Reason = term()

              OPTIONAL

              This function is called before init_per_testcase if  it  exists.
              It  behaves the same way as pre_init_per_suite, but for function
              init_per_testcase instead.

              If Module:pre_init_per_testcase/4 is not  exported,  common_test
              will  attempt to call Module:pre_init_per_testcase(TestcaseName,
              InitData, CTHState) instead. This is for  backwards  compatibil-
              ity.

              CTHs  cannot  be added here right now. That feature may be added
              in a later release, but it would right now break backwards  com-
              patibility.

       Module:post_init_per_testcase(SuiteName,  TestcaseName, Config, Return,
       CTHState) -> Result

              Types:

                 SuiteName = atom()
                 TestcaseName = atom()
                 Config = [{Key,Value}]
                 Return = NewReturn = Config | SkipOrFail | term()
                 SkipOrFail = {fail,Reason} | {skip, Reason}
                 CTHState = NewCTHState = term()
                 Result = {NewReturn, NewCTHState}
                 Key = atom()
                 Value = term()
                 Reason = term()

              OPTIONAL

              This function is called after init_per_testcase if it exists. It
              behaves  the  same  way as post_init_per_suite, but for function
              init_per_testcase instead.

              If Module:post_init_per_testcase/5 is not exported,  common_test
              will attempt to call Module:post_init_per_testcase(TestcaseName,
              Config, Return, CTHState) instead. This is for backwards compat-
              ibility.

       Module:pre_end_per_testcase(SuiteName, TestcaseName, EndData, CTHState)
       -> Result

              Types:

                 SuiteName = atom()
                 TestcaseName = atom()
                 EndData = Config
                 Config = NewConfig = [{Key,Value}]
                 CTHState = NewCTHState = term()
                 Result = {NewConfig, NewCTHState}
                 Key = atom()
                 Value = term()
                 Reason = term()

              OPTIONAL

              This function is called before end_per_testcase if it exists. It
              behaves  the  same  way  as  pre_end_per_suite, but for function
              end_per_testcase instead.

              This function cannot change the  result  of  the  test  case  by
              returning skip or fail tuples, but it may insert items in Config
              that can be read in end_per_testcase/2 or in  post_end_per_test-
              case/5.

              If  Module:pre_end_per_testcase/4  is  not exported, common_test
              will attempt to  call  Module:pre_end_per_testcase(TestcaseName,
              EndData, CTHState) instead. This is for backwards compatibility.

       Module:post_end_per_testcase(SuiteName,  TestcaseName,  Config, Return,
       CTHState) -> Result

              Types:

                 SuiteName = atom()
                 TestcaseName = atom()
                 Config = [{Key,Value}]
                 Return = NewReturn = Config | SkipOrFail | term()
                 SkipOrFail = {fail,Reason} | {skip, Reason}
                 CTHState = NewCTHState = term()
                 Result = {NewReturn, NewCTHState}
                 Key = atom()
                 Value = term()
                 Reason = term()

              OPTIONAL

              This function is called after end_per_testcase if it exists.  It
              behaves  the  same  way  as post_end_per_suite, but for function
              end_per_testcase instead.

              If Module:post_end_per_testcase/5 is not  exported,  common_test
              will  attempt to call Module:post_end_per_testcase(TestcaseName,
              Config, Return, CTHState) instead. This is for backwards compat-
              ibility.

       Module:pre_end_per_group(SuiteName,  GroupName,  EndData,  CTHState) ->
       Result

              Types:

                 SuiteName = atom()
                 GroupName = atom()
                 EndData = Config | SkipOrFail
                 Config = NewConfig = [{Key,Value}]
                 CTHState = NewCTHState = term()
                 Result = {NewConfig | SkipOrFail, NewCTHState}
                 SkipOrFail = {fail,Reason} | {skip, Reason}
                 Key = atom()
                 Value = term()
                 Reason = term()

              OPTIONAL

              This function is called before end_per_group if  it  exists.  It
              behaves  the  same  way  as pre_init_per_suite, but for function
              end_per_group instead.

              If Module:pre_end_per_group/4 is not exported, common_test  will
              attempt  to  call  Module:pre_end_per_group(GroupName,  EndData,
              CTHState) instead. This is for backwards compatibility.

       Module:post_end_per_group(SuiteName, GroupName,  Config,  Return,  CTH-
       State) -> Result

              Types:

                 SuiteName = atom()
                 GroupName = atom()
                 Config = [{Key,Value}]
                 Return = NewReturn = Config | SkipOrFail | term()
                 SkipOrFail = {fail,Reason} | {skip, Reason}
                 CTHState = NewCTHState = term()
                 Result = {NewReturn, NewCTHState}
                 Key = atom()
                 Value = term()
                 Reason = term()

              OPTIONAL

              This  function  is  called  after end_per_group if it exists. It
              behaves the same way as post_init_per_suite,  but  for  function
              end_per_group instead.

              If Module:post_end_per_group/5 is not exported, common_test will
              attempt  to  call  Module:post_end_per_group(GroupName,  Config,
              Return, CTHState) instead. This is for backwards compatibility.

       Module:pre_end_per_suite(SuiteName, EndData, CTHState) -> Result

              Types:

                 SuiteName = atom()
                 EndData = Config | SkipOrFail
                 Config = NewConfig = [{Key,Value}]
                 CTHState = NewCTHState = term()
                 Result = {NewConfig | SkipOrFail, NewCTHState}
                 SkipOrFail = {fail,Reason} | {skip, Reason}
                 Key = atom()
                 Value = term()
                 Reason = term()

              OPTIONAL

              This  function  is  called before end_per_suite if it exists. It
              behaves the same way as  pre_init_per_suite,  but  for  function
              end_per_suite instead.

       Module:post_end_per_suite(SuiteName,   Config,   Return,  CTHState)  ->
       Result

              Types:

                 SuiteName = atom()
                 Config = [{Key,Value}]
                 Return = NewReturn = Config | SkipOrFail | term()
                 SkipOrFail = {fail,Reason} | {skip, Reason}
                 CTHState = NewCTHState = term()
                 Result = {NewReturn, NewCTHState}
                 Key = atom()
                 Value = term()
                 Reason = term()

              OPTIONAL

              This function is called after end_per_suite  if  it  exists.  It
              behaves  the  same  way as post_init_per_suite, but for function
              end_per_suite instead.

       Module:on_tc_fail(SuiteName, TestName, Reason, CTHState) -> NewCTHState

              Types:

                 SuiteName = atom()
                 TestName    =    init_per_suite     |     end_per_suite     |
                 {init_per_group,GroupName}   |   {end_per_group,GroupName}  |
                 {FuncName,GroupName} | FuncName
                 FuncName = atom()
                 GroupName = atom()
                 Reason = term()
                 CTHState = NewCTHState = term()

              OPTIONAL

              This function is called whenever a test case  (or  configuration
              function)  fails. It is called after the post function is called
              for the failed test case, that is:

                * If init_per_suite  fails,  this  function  is  called  after
                  post_init_per_suite.

                * If   a  test  case  fails,  this  funcion  is  called  after
                  post_end_per_testcase.

              If the failed test case belongs to a test case group, the  first
              argument  is  a  tuple  {FuncName,GroupName}, otherwise only the
              function name.

              The data that comes with Reason follows the same format as Fail-
              Reason in event tc_done. For details, see section Event Handling
              in the User's Guide.

              If Module:on_tc_fail/4 is not exported, common_test will attempt
              to  call  Module:on_tc_fail(TestName, Reason, CTHState) instead.
              This is for backwards compatibility.

       Module:on_tc_skip(SuiteName, TestName, Reason, CTHState) -> NewCTHState

              Types:

                 SuiteName = atom()
                 TestName    =    init_per_suite     |     end_per_suite     |
                 {init_per_group,GroupName}   |   {end_per_group,GroupName}  |
                 {FuncName,GroupName} | FuncName
                 FuncName = atom()
                 GroupName = atom()
                 Reason = {tc_auto_skip | tc_user_skip, term()}
                 CTHState = NewCTHState = term()

              OPTIONAL

              This function is called whenever a test case  (or  configuration
              function)  is  skipped.  It is called after the post function is
              called for the skipped test case, that is:

                * If init_per_group is skipped, this function is called  after
                  post_init_per_group.

                * If  a  test  case  is skipped, this function is called after
                  post_end_per_testcase.

              If the skipped test case belongs to a test case group, the first
              argument  is  a  tuple  {FuncName,GroupName}, otherwise only the
              function name.

              The data that comes with  Reason  follows  the  same  format  as
              events  tc_auto_skip  and  tc_user_skip For details, see section
              Event Handling in the User's Guide.

              If Module:on_tc_skip/4 is not exported, common_test will attempt
              to  call  Module:on_tc_skip(TestName, Reason, CTHState) instead.
              This is for backwards compatibility.

       Module:terminate(CTHState)

              Types:

                 CTHState = term()

              OPTIONAL

              This function is called at the end of a CTH scope.

       Module:id(Opts) -> Id

              Types:

                 Opts = term()
                 Id = term()

              OPTIONAL

              The Id identifies a CTH instance uniquely. If  two  CTHs  return
              the  same  Id, the second CTH is ignored and subsequent calls to
              the CTH are only made to the first instance.  For  details,  see
              section Installing a CTH in the User's Guide.

              This  function  is  not  to  have any side effects, as it can be
              called multiple times by Common Test.

              If not implemented, the CTH acts as if this function returned  a
              call to make_ref/0.



Ericsson AB                    common_test 1.22                    ct_hooks(3)