查看源代码 ct_hooks 行为 (common_test v1.27.5)
Common Test 之上的回调接口。
Common Test Hook (CTH) 框架允许通过在所有测试套件调用之前和之后的回调来扩展 Common Test
的默认行为。它适用于 Common Test
的高级用户,他们希望抽象出多个测试套件通用的行为。
简而言之,CTH 允许您:
- 在每次套件配置调用之前操作运行时配置。
- 操作所有套件配置调用的返回值,以及由此产生的测试结果。
以下各节描述了 Common Test
在测试执行期间调用的强制性和可选的 CTH 函数。有关更多详细信息,请参阅用户指南中的Common Test 钩子部分。
有关如何向套件添加 CTH 的信息,请参阅用户指南中的安装 CTH部分。
注意
有关 CTH 的最小示例,请参阅用户指南中的示例 CTH部分。
摘要
回调:回调函数
Id
唯一标识 CTH 实例。如果两个 CTH 返回相同的 Id
,则第二个 CTH 将被忽略,并且对 CTH 的后续调用仅对第一个实例进行。有关详细信息,请参阅用户指南中的安装 CTH部分。
此函数始终在任何其他回调函数之前调用。使用它来初始化任何公共状态。它会为此 CTH 返回一个状态。
每当测试用例(或配置函数)失败时,都会调用此函数。它在为失败的测试用例调用 post 函数后调用。
每当测试用例(或配置函数)被跳过时,都会调用此函数。它在为跳过的测试用例调用 post 函数后调用。
此函数在 all/0
之后调用。它用于修改要执行的测试用例和测试组的集合,例如添加或删除测试用例和组,更改组属性,甚至跳过套件中的所有测试。
如果存在,则在 end_per_group
之后调用此函数。它的行为与 post_init_per_suite
相同,但适用于函数 end_per_group。
如果存在,则在 end_per_suite
之后调用此函数。它的行为与 post_init_per_suite
相同,但适用于函数 end_per_suite
。
如果存在,则在 end_per_testcase
之后调用此函数。它的行为与 post_end_per_suite
相同,但适用于函数 end_per_testcase
。
此函数在 groups/0
之后调用。它用于修改测试组定义,例如添加或删除组或更改组属性。
如果存在,则在 init_per_group
之后调用此函数。它的行为与 post_init_per_suite
相同,但适用于函数 init_per_group
。
如果存在,则在 init_per_suite
之后调用此函数。它通常包含额外的检查,以确保所有正确的依赖项都已正确启动。
如果存在,则在 init_per_testcase
之后调用此函数。它的行为与 post_init_per_suite
相同,但适用于函数 init_per_testcase
。
如果存在,则在 end_per_group
之前调用此函数。它的行为与 pre_init_per_suite
相同,但适用于函数 end_per_group
。
如果存在,则在 end_per_suite
之前调用此函数。它的行为与 pre_init_per_suite
相同,但适用于函数 end_per_suite
。
如果存在,则在 end_per_testcase
之前调用此函数。它的行为与 pre_end_per_suite
相同,但适用于函数 end_per_testcase
。
如果存在,则在 init_per_group
之前调用此函数。它的行为与 pre_init_per_suite
相同,但适用于函数 init_per_group
。
如果存在,则在 init_per_suite
之前调用此函数。它通常包含必须在调用 init_per_suite
之前完成的初始化/日志记录。如果返回 {skip,Reason}
或 {fail,Reason}
,则会跳过 init_per_suite
和套件的所有测试用例,并在套件的概览日志中打印 Reason
。
如果存在,则在 init_per_testcase
之前调用此函数。它的行为与 pre_init_per_suite
相同,但适用于函数 init_per_testcase
。
此函数在 CTH 范围的末尾调用。返回的术语将被忽略。
回调:回调函数
Id
唯一标识 CTH 实例。如果两个 CTH 返回相同的 Id
,则第二个 CTH 将被忽略,并且对 CTH 的后续调用仅对第一个实例进行。有关详细信息,请参阅用户指南中的安装 CTH部分。
此函数不会产生任何副作用,因为它可能会被 Common Test
多次调用。
如果未实现,则 CTH 的行为就好像此函数返回对 make_ref/0
的调用。
-callback init(Id, Opts) -> {ok, State} | {ok, State, Priority} when Id :: reference() | term(), Opts :: term(), State :: term(), Priority :: integer().
此函数始终在任何其他回调函数之前调用。使用它来初始化任何公共状态。它会为此 CTH 返回一个状态。
Id
是 ct_hooks:id/1
的返回值,或者如果未实现 ct_hooks:id/1
,则为 reference
(使用 erlang:make_ref/0
在 ERTS 中创建)。
Priority
是此钩子的相对优先级。优先级较低的钩子首先执行。如果未指定优先级,则将其设置为 0
。
有关钩子执行顺序的详细信息,请参阅用户指南中的CTH 执行顺序部分。
有关何时调用 init
的详细信息,请参阅用户指南中的CTH 范围部分。
-callback on_tc_fail(SuiteName, TestName, Reason, CTHState) -> NewCTHState when 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 :: term(), NewCTHState :: term().
每当测试用例(或配置函数)失败时,都会调用此函数。它在为失败的测试用例调用 post 函数后调用。
也就是说
- 如果
init_per_suite
失败,则在post_init_per_suite
之后调用此函数。 - 如果测试用例失败,则在
post_end_per_testcase
之后调用此函数。
如果失败的测试用例属于测试用例组,则第二个参数是元组 {FuncName,GroupName}
,否则仅是函数名称。
与 Reason
一起出现的数据格式与事件 tc_done
中的 FailReason
相同。有关详细信息,请参阅用户指南中的事件处理部分。
如果未导出 Module:on_tc_fail/4
,则 common_test 将尝试调用 Module:on_tc_fail(TestName, Reason, CTHState)
。这是为了向后兼容。
-callback on_tc_skip(SuiteName, TestName, Reason, CTHState) -> NewCTHState when 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 :: term(), NewCTHState :: term().
每当测试用例(或配置函数)被跳过时,都会调用此函数。它在为跳过的测试用例调用 post 函数后调用。
也就是说
- 如果跳过
init_per_group
,则在post_init_per_group
之后调用此函数。 - 如果跳过测试用例,则在
post_end_per_testcase
之后调用此函数。
如果跳过的测试用例属于测试用例组,则第二个参数是元组 {FuncName,GroupName}
,否则仅是函数名称。
与 Reason
一起出现的数据格式与事件 tc_auto_skip
和 tc_user_skip
相同。有关详细信息,请参阅用户指南中的事件处理部分。
如果未导出 Module:on_tc_skip/4
,则 common_test 将尝试调用 Module:on_tc_skip(TestName, Reason, CTHState)
。这是为了向后兼容。
-callback post_all(SuiteName, Return, GroupDefs) -> NewReturn when SuiteName :: atom(), Return :: Tests | {skip, Reason}, 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, Properties, 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 :: [Group], Group :: {GroupName, GroupProperties, GroupsAndTestCases}, GroupProperties :: [parallel | sequence | Shuffle | {GroupRepeatType, N}], GroupsAndTestCases :: [Group | {group, GroupName} | TestCase], Reason :: term().
此函数在 all/0
之后调用。它用于修改要执行的测试用例和测试组的集合,例如添加或删除测试用例和组,更改组属性,甚至跳过套件中的所有测试。
Return
是 all/0
返回的内容,即要执行的测试用例和组的列表,或元组 {skip,Reason}
。
GroupDefs
是 groups/0
或 post_groups/2
钩子返回的结果,即组定义的列表。
NewReturn
是可能被修改后的 Return
版本。
此函数仅在 CTH 在 init_per_suite
运行之前添加时才会被调用。有关详细信息,请参阅用户指南中的 CTH 作用域 部分。
请注意,对于通过 suite/0
函数安装的 CTH,post_all/2
会在 init/2
钩子函数之前被调用。但是,对于通过 CT 启动标志安装的 CTH,init/2
函数会首先被调用。
注意
在每次测试执行之前,Common Test 会执行一次模拟测试运行,以便统计用于日志记录的测试套件、组和用例的数量。这会导致
post_all/3
钩子函数总是被调用两次。因此,最好在此回调中避免副作用。
-callback post_end_per_group(SuiteName, GroupName, Config, Return, CTHState) -> Result when SuiteName :: atom(), GroupName :: atom(), Config :: [{Key, Value}], Return :: Config | SkipOrFail | term(), NewReturn :: Config | SkipOrFail | term(), SkipOrFail :: {fail, Reason} | {skip, Reason}, CTHState :: term(), NewCTHState :: term(), Result :: {NewReturn, NewCTHState}, Key :: atom(), Value :: term(), Reason :: term().
如果存在,则在 end_per_group
之后调用此函数。它的行为与 post_init_per_suite
相同,但适用于函数 end_per_group。
如果 Module:post_end_per_group/5
没有导出,则 common_test 将尝试调用 Module:post_end_per_group(GroupName, Config, Return, CTHState)
来代替。这是为了向后兼容。
-callback post_end_per_suite(SuiteName, Config, Return, CTHState) -> Result when SuiteName :: atom(), Config :: [{Key, Value}], Return :: Config | SkipOrFail | term(), NewReturn :: Config | SkipOrFail | term(), SkipOrFail :: {fail, Reason} | {skip, Reason}, CTHState :: term(), NewCTHState :: term(), Result :: {NewReturn, NewCTHState}, Key :: atom(), Value :: term(), Reason :: term().
如果存在,则在 end_per_suite
之后调用此函数。它的行为与 post_init_per_suite
相同,但适用于函数 end_per_suite
。
post_end_per_testcase(SuiteName, TestcaseName, Config, Return, CTHState)
查看源代码 (可选) (自 OTP 19.3 起)-callback post_end_per_testcase(SuiteName, TestcaseName, Config, Return, CTHState) -> Result when SuiteName :: atom(), TestcaseName :: atom(), Config :: [{Key, Value}], Return :: Config | SkipOrFail | term(), NewReturn :: Config | SkipOrFail | term(), SkipOrFail :: {fail, Reason} | {skip, Reason}, CTHState :: term(), NewCTHState :: term(), Result :: {NewReturn, NewCTHState}, Key :: atom(), Value :: term(), Reason :: term().
如果存在,则在 end_per_testcase
之后调用此函数。它的行为与 post_end_per_suite
相同,但适用于函数 end_per_testcase
。
如果 Module:post_end_per_testcase/5
没有导出,则 common_test 将尝试调用 Module:post_end_per_testcase(TestcaseName, Config, Return, CTHState)
来代替。这是为了向后兼容。
-callback post_groups(SuiteName, GroupDefs) -> NewGroupDefs when SuiteName :: atom(), GroupDefs :: [Group], NewGroupDefs :: [Group], Group :: {GroupName, Properties, GroupsAndTestCases}, GroupName :: atom(), Properties :: [parallel | sequence | Shuffle | {GroupRepeatType, 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.
此函数在 groups/0
之后调用。它用于修改测试组定义,例如添加或删除组或更改组属性。
GroupDefs
是 groups/0
返回的结果,即组定义的列表。
NewGroupDefs
是这个列表的可能被修改后的版本。
此函数仅在 CTH 在 init_per_suite
运行之前添加时才会被调用。有关详细信息,请参阅用户指南中的 CTH 作用域 部分。
请注意,对于通过 suite/0
函数安装的 CTH,post_groups/2
会在 init/2
钩子函数之前被调用。但是,对于通过 CT 启动标志安装的 CTH,init/2
函数会首先被调用。
注意
在每次测试执行之前,Common Test 会执行一次模拟测试运行,以便统计用于日志记录的测试套件、组和用例的数量。这会导致
post_groups/2
钩子函数总是被调用两次。因此,最好在此回调中避免副作用。
post_init_per_group(SuiteName, GroupName, Config, Return, CTHState)
查看源代码 (可选) (自 OTP 19.3 起)-callback post_init_per_group(SuiteName, GroupName, Config, Return, CTHState) -> Result when SuiteName :: atom(), GroupName :: atom(), Config :: [{Key, Value}], Return :: Config | SkipOrFail | term(), NewReturn :: Config | SkipOrFail | term(), SkipOrFail :: {fail, Reason} | {skip, Reason}, CTHState :: term(), NewCTHState :: term(), Result :: {NewReturn, NewCTHState}, Key :: atom(), Value :: term(), Reason :: term().
如果存在,则在 init_per_group
之后调用此函数。它的行为与 post_init_per_suite
相同,但适用于函数 init_per_group
。
如果 Module:post_init_per_group/5
没有导出,则 common_test 将尝试调用 Module:post_init_per_group(GroupName, Config, Return, CTHState)
来代替。这是为了向后兼容。
-callback post_init_per_suite(SuiteName, Config, Return, CTHState) -> Result when SuiteName :: atom(), Config :: [{Key, Value}], Return :: Config | SkipOrFail | term(), NewReturn :: Config | SkipOrFail | term(), SkipOrFail :: {fail, Reason} | {skip, Reason} | term(), CTHState :: term(), NewCTHState :: term(), Result :: {NewReturn, NewCTHState}, Key :: atom(), Value :: term(), Reason :: term().
如果存在,则在 init_per_suite
之后调用此函数。它通常包含额外的检查,以确保所有正确的依赖项都已正确启动。
Return
是 init_per_suite
返回的结果,即 {fail,Reason}
、{skip,Reason}
、Config
列表,或者描述 init_per_suite
如何失败的项。
NewReturn
是 init_per_suite
的可能被修改后的返回值。要从 init_per_suite
中的失败中恢复,请返回删除 tc_status
元素的 ConfigList
。有关更多详细信息,请参阅用户指南中“操作测试”部分的 后置钩子。
CTHState
是 CTH 的当前内部状态。
此函数仅在 CTH 在 init_per_suite
之前或之中添加时才会被调用。有关详细信息,请参阅用户指南中的 CTH 作用域 部分。
post_init_per_testcase(SuiteName, TestcaseName, Config, Return, CTHState)
查看源代码 (可选) (自 OTP 19.3 起)-callback post_init_per_testcase(SuiteName, TestcaseName, Config, Return, CTHState) -> Result when SuiteName :: atom(), TestcaseName :: atom(), Config :: [{Key, Value}], Return :: Config | SkipOrFail | term(), NewReturn :: Config | SkipOrFail | term(), SkipOrFail :: {fail, Reason} | {skip, Reason}, CTHState :: term(), NewCTHState :: term(), Result :: {NewReturn, NewCTHState}, Key :: atom(), Value :: term(), Reason :: term().
如果存在,则在 init_per_testcase
之后调用此函数。它的行为与 post_init_per_suite
相同,但适用于函数 init_per_testcase
。
如果 Module:post_init_per_testcase/5
没有导出,则 common_test 将尝试调用 Module:post_init_per_testcase(TestcaseName, Config, Return, CTHState)
来代替。这是为了向后兼容。
-callback pre_end_per_group(SuiteName, GroupName, EndData, CTHState) -> Result when SuiteName :: atom(), GroupName :: atom(), EndData :: Config | SkipOrFail, Config :: [{Key, Value}], NewConfig :: [{Key, Value}], CTHState :: term(), NewCTHState :: term(), Result :: {NewConfig | SkipOrFail, NewCTHState}, SkipOrFail :: {fail, Reason} | {skip, Reason}, Key :: atom(), Value :: term(), Reason :: term().
如果存在,则在 end_per_group
之前调用此函数。它的行为与 pre_init_per_suite
相同,但适用于函数 end_per_group
。
如果 Module:pre_end_per_group/4
没有导出,则 common_test 将尝试调用 Module:pre_end_per_group(GroupName, EndData, CTHState)
来代替。这是为了向后兼容。
-callback pre_end_per_suite(SuiteName, EndData, CTHState) -> Result when SuiteName :: atom(), EndData :: Config | SkipOrFail, Config :: [{Key, Value}], NewConfig :: [{Key, Value}], CTHState :: term(), NewCTHState :: term(), Result :: {NewConfig | SkipOrFail, NewCTHState}, SkipOrFail :: {fail, Reason} | {skip, Reason}, Key :: atom(), Value :: term(), Reason :: term().
如果存在,则在 end_per_suite
之前调用此函数。它的行为与 pre_init_per_suite
相同,但适用于函数 end_per_suite
。
-callback pre_end_per_testcase(SuiteName, TestcaseName, EndData, CTHState) -> Result when SuiteName :: atom(), TestcaseName :: atom(), EndData :: Config, Config :: [{Key, Value}], NewConfig :: [{Key, Value}], CTHState :: term(), NewCTHState :: term(), Result :: {NewConfig, NewCTHState}, Key :: atom(), Value :: term().
如果存在,则在 end_per_testcase
之前调用此函数。它的行为与 pre_end_per_suite
相同,但适用于函数 end_per_testcase
。
此函数不能通过返回 skip 或 fail 元组来更改测试用例的结果,但它可以在 Config
中插入可在 end_per_testcase/2
或 post_end_per_testcase/5
中读取的项。
如果 Module:pre_end_per_testcase/4
没有导出,则 common_test 将尝试调用 Module:pre_end_per_testcase(TestcaseName, EndData, CTHState)
来代替。这是为了向后兼容。
-callback pre_init_per_group(SuiteName, GroupName, InitData, CTHState) -> Result when SuiteName :: atom(), GroupName :: atom(), InitData :: Config | SkipOrFail, Config :: [{Key, Value}], NewConfig :: [{Key, Value}], CTHState :: term(), NewCTHState :: term(), Result :: {NewConfig | SkipOrFail, NewCTHState}, SkipOrFail :: {fail, Reason} | {skip, Reason}, Key :: atom(), Value :: term(), Reason :: term().
如果存在,则在 init_per_group
之前调用此函数。它的行为与 pre_init_per_suite
相同,但适用于函数 init_per_group
。
如果 Module:pre_init_per_group/4
没有导出,则 common_test 将尝试调用 Module:pre_init_per_group(GroupName, InitData, CTHState)
来代替。这是为了向后兼容。
-callback pre_init_per_suite(SuiteName, InitData, CTHState) -> Result when SuiteName :: atom(), InitData :: Config | SkipOrFail, Config :: [{Key, Value}], NewConfig :: [{Key, Value}], CTHState :: term(), NewCTHState :: term(), Result :: {Return, NewCTHState}, Return :: NewConfig | SkipOrFail, SkipOrFail :: {fail, Reason} | {skip, Reason}, Key :: atom(), Value :: term(), Reason :: term().
如果存在,则在 init_per_suite
之前调用此函数。它通常包含必须在调用 init_per_suite
之前完成的初始化/日志记录。如果返回 {skip,Reason}
或 {fail,Reason}
,则会跳过 init_per_suite
和套件的所有测试用例,并在套件的概览日志中打印 Reason
。
SuiteName
是要运行的套件的名称。
InitData
是测试套件的原始配置列表,或者如果先前的 CTH 返回此值,则为 SkipOrFail
元组。
CTHState
是 CTH 的当前内部状态。
Return
是 init_per_suite
函数的结果。如果它是 {skip,Reason}
或 {fail,Reason}
,则永远不会调用 init_per_suite
,而是分别认为初始化被跳过或失败。如果返回 NewConfig
列表,则使用该 NewConfig
列表调用 init_per_suite
。有关更多详细信息,请参阅用户指南中的 前置钩子 部分。
此函数仅在 CTH 在 init_per_suite
运行之前添加时才会被调用。有关详细信息,请参阅用户指南中的 CTH 作用域 部分。
-callback pre_init_per_testcase(SuiteName, TestcaseName, InitData, CTHState) -> Result when SuiteName :: atom(), TestcaseName :: atom(), InitData :: Config | SkipOrFail, Config :: [{Key, Value}], NewConfig :: [{Key, Value}], CTHState :: term(), NewCTHState :: term(), Result :: {NewConfig | SkipOrFail, NewCTHState}, SkipOrFail :: {fail, Reason} | {skip, Reason}, Key :: atom(), Value :: term(), Reason :: term().
如果存在,则在 init_per_testcase
之前调用此函数。它的行为与 pre_init_per_suite
相同,但适用于函数 init_per_testcase
。
如果 Module:pre_init_per_testcase/4
没有导出,则 common_test 将尝试调用 Module:pre_init_per_testcase(TestcaseName, InitData, CTHState)
来代替。这是为了向后兼容。
现在不能在此处添加 CTH。此功能可能会在以后的版本中添加,但现在会破坏向后兼容性。
此函数在 CTH 范围的末尾调用。返回的术语将被忽略。