本主题说明如何使用桩函数回调进行动态桩函数配置。
此章节:
桩函数回调为编程指定于测试用例的桩函数逻辑提供了强大的机制。对于每个测试用例,您可以定义在测试用例执行期间每次调用桩函数时要执行的特定桩函数行为。C++test 自动生成运行特定于测试用例的桩函数逻辑的代码,因此您无需修改主桩函数定义。
您可以通过以下方式之一配置桩函数回调:
测试用例编辑器会自动生成桩函数回调框架的可配置组件,显示有关桩函数配置的建议,并在创建桩函数回调后对其进行注册。
每个 C/C++test 的桩函数都将其默认逻辑内置到桩函数定义中-通常,桩函数仅返回简单/默认返回值。如果桩函数未定义桩函数回调函数,则调用桩函数时 C++test 将使用默认逻辑。另外,如果未定义测试专用的桩函数逻辑,则可以配置 C/C++test 调用原始函数,请参见创建调用原始函数的桩函数。 |
在创建桩函数之前,请确保在【桩函数】视图中启用启用桩函数回调 选项(请参见【桩函数】视图中的【配置桩函数】选项) 或在测试配置中 (参见 执行选项卡设置-定义测试的执行方式) 。 |
有关使用【测试用例编辑器】配置桩函数行为的更多详细信息,请参见 使用【测试用例编辑器】添加测试套件和测试用例-配置桩函数行为 。
使用 生成自动桩函数或创建用户桩函数 选项为您要配置的功能创建桩函数(请参见 添加和修改桩函数)。
将桩函数回调函数添加到测试套件文件。
使用可用的输入/输出参数在桩函数回调函数中定义桩函数逻辑。
|
导航到测试用例定义,并使用以下宏注册桩函数回调:CPPTEST_REGISTER_STUB_CALLBACK(<STUB_ID>, &<STUB_CALLBACK_NAME>)
|
在调用被测函数之前,请确保已注册回调。 |
请参见Stub Callback Details有关桩函数回调功能和桩函数回调注册的更多信息。
桩函数回调框架包含以下组件:
桩函数回调函数是用户定义的 C/C++ 函数,其中包含要在调用相关桩函数时执行的逻辑。它具有从桩函数/桩函数函数的签名派生的唯一签名:
void <CALLBACK_NAME>(CppTest_StubCallInfo* stubCallInfo, <STUB_IN_OUT_PARAMETERS>) |
桩函数回调函数的接口包括桩函数函数的所有输入/输出参数(<STUB_IN_OUT_PARAMETERS>
),以及其他帮助程序参数(stubCallInfo
)。您还可以自定义桩函数回调函数的名称 (<CALLBACK_NAME>
)。
以下示例演示了如何为int processValues(int i, int j);
自定义桩函数回调函数;函数:
void CppTest_StubCallback_processValues_case_1(CppTest_StubCallInfo* stubCallInfo, int* __return, int i, int j) { // checking input value CPPTEST_ASSERT_INTEGER_EQUAL(-1, i); // modifying return value *__return = 150; } |
我们建议您将桩函数回调函数以及相关的测试用例定义保留在同一测试套件文件中。 |
您可以将桩函数回调函数定义为测试套件类的全局函数或静态成员函数(仅限 C++)。当启用“访问私有成员代码”检测功能时,这允许桩函数回调函数访问被测代码的私有类成员。
使用以下桩函数回调接口,可以用任何有效的 C 或 C++ 代码表示自定义桩函数逻辑:
__return
"指针 __this
"指针 int stubCallInfo->callNo
"变量此外,您可以在 Stub 回调函数中使用全局变量或全局函数,包括 C++test 单元测试 API(例如, CPPTEST_ASSERT
和 CPPTEST_REPORT
)。如果桩函数函数的原始定义可用,则也可以从桩函数回调函数中执行它。
您可以在【测试套件】文件中定义多个【桩函数回调函数】- 它们可以对应于相同的桩函数或多个不同的桩函数。
一个桩函数回调函数可以在单个测试用例中使用,也可以在许多不同的测试用例中共享。
一个桩函数一次只能激活一个桩函数回调函数(请参见 Stub Callback Registration)。
为了使桩函数回调函数有效,必须对其进行注册。该函数通常在第一次调用桩函数函数之前在相关的测试用例中注册。在大多数情况下,应在调用被测函数之前进行注册。
使用以下 API 调用来注册桩函数回调函数:
CPPTEST_REGISTER_STUB_CALLBACK(<STUB_ID>, &<STUB_CALLBACK_NAME>) |
此处:
<STUB_ID>
是唯一的桩函数标识符 (请参见 Stub Callback Execution)<STUB_CALLBACK_NAME>
是用户定义的桩函数回调函数的名称示例:
CPPTEST_REGISTER_STUB_CALLBACK("processValues", &CppTest_StubCallback_processValues_case_1); |
您可以在多个测试用例中注册相同的桩函数回调函数,以便每个测试用例针对给定的桩函数使用相同的自定义逻辑。同样,可以在一个测试用例中注册不同的桩函数回调函数(针对不同的桩函数)。这使测试用例能够为多个桩函数提供自定义行为。在任何给定时间,给定桩函数只能有一个活跃的桩函数回调功能。
桩函数回调函数的生存期:
CPPTEST_REGISTER_STUB_CALLBACK(<STUB_ID>, &<STUB_CALLBACK_NAME>)
<STUB_ID>
)示例:
void test_case_1() { ... // CppTest_StubCallback_foo activation: CPPTEST_REGISTER_STUB_CALLBACK("foo", &CppTest_StubCallback_foo); // CppTest_StubCallback_bar activation: CPPTEST_REGISTER_STUB_CALLBACK("bar", &CppTest_StubCallback_bar); ... callToFunctionUnderTest(); // will call foo() and bar() ... } // end of test case: CppTest_StubCallback_foo deactivation, CppTest_StubCallback_bar deactivation void test_case_2() { ... // CppTest_StubCallback_foo activation: CPPTEST_REGISTER_STUB_CALLBACK("foo", &CppTest_StubCallback_foo); // CppTest_StubCallback_bar activation: CPPTEST_REGISTER_STUB_CALLBACK("bar", &CppTest_StubCallback_bar); ... callToFunctionUnderTest(); // will call foo() and bar() ... // CppTest_StubCallback_foo_1 activation, CppTest_StubCallback_foo deactivation CPPTEST_REGISTER_STUB_CALLBACK("foo", &CppTest_StubCallback_foo_1); } // end of test case: CppTest_StubCallback_foo_1 deactivation, CppTest_StubCallback_bar deactivation |
如果定义并注册了桩函数回调函数,则每次调用相应的桩函数都会执行该函数。回调函数通过
, 来调用,如果在创建桩函数时启用了【启用桩函数回调】选项(默认情况下启用此选项),则该函数会自动添加到桩函数定义中。CPPTEST_STUB_INVOKE_CALLBACK()
示例:
/** Auto-generated stub definition for function: int processValues(int, int) */ int processValues (int i, int j) ; int CppTest_Auto_Stub_processValues (int i, int j) { CPPTEST_STUB_CALLED("processValues"); int __return = 0; /** * This section enables Dynamic Stub Configuration with Stub Callbacks. * * IMPORTANT: THIS COMMENT BLOCK SHOULD NOT BE DELETED OR MODIFIED * * 1. Define stub callback function in test suite file - use the following signature: * void CppTest_StubCallback_SomeName(CppTest_StubCallInfo* stubCallInfo, int* __return, int i, int j) * * 2. Register stub callback in test case function - use the following code: * CPPTEST_REGISTER_STUB_CALLBACK("processValues", &CppTest_StubCallback_SomeName); * * 3. Fill out the body of the stub callback function according to intent. * The following line may be used to call original function inside stub callback: * *__return = ::processValues(i, j); */ if (CPPTEST_STUB_HAS_CALLBACK()) { CPPTEST_STUB_CALLBACK_PARAMS(int* __return, int i, int j); CPPTEST_STUB_INVOKE_CALLBACK(&__return, i, j); } else { /* You can put additional stub logic here. */ } return __return; } |
自动添加到桩函数定义的桩函数回调调用部分包含桩函数回调函数的默认签名和示例性的桩函数回调注册行,当您手动配置桩函数回调时,可以将其复制到测试套件文件中。
用于桩函数回调注册和桩函数回调执行的桩函数标识符必须唯一,以标识各个桩函数。默认情况下, C++test 生成的桩函数按照以下模式使用标识符:
[<parent::>]<function_name> |
仅当桩函数函数是类或名称空间成员时,才添加<parent::>
前缀。仅添加直接父级。对于模板类方法、父名称中省略了模板参数。
C/C++test 对函数的所有重载版本使用相同的函数标识符(请参见桩函数标识符)。在对重载函数使用桩函数回调之前,请更新用于桩函数回调执行代码 (CPPTEST_STUB_CALLED()
) 和桩函数回调注册的标识符,以确保它们是唯一的。这将使您能够区分重载的函数/方法的桩函数。
示例:
用于所有重载版本的 foo() 的默认标识符:
CPPTEST_STUB_CALLED("foo"); |
Foo(int) 的更新的标识符:
CPPTEST_STUB_CALLED("foo_int") |
如果没有在测试用例中注册特定于测试用例的桩函数回调函数,则 C/C++test 允许您生成调用原始函数的桩函数。为此,请在 桩函数视图中启用以下选项 (请参见 桩函数视图中的配置桩函数选项) 或在测试配置中(请参见 执行选项卡设置-定义测试的执行方式):
启用这些选项后,C/C++test 将应用以下桩函数策略:
示例:
以下情况不支持调用原始函数: