在软件测试工具Parasoft C/C++test中,桩函数是其实现高覆盖率单元测试的核心机制之一,是用于模拟被测函数所依赖的外部组件的测试工具。它的核心作用是接管这些外部调用,并允许测试人员预设其行为,例如强制返回特定值或修改输出参数。通过故意改变传递给主函数的参数值,可以精准控制测试输入,从而验证主函数在不同场景下的逻辑是否正确,确保其能够妥善处理各种正常与异常情况。

>>点击获取Parasoft C/C++test试用
我们用Parasoft C/C++test通过桩函数的方式来控制输入的参数,去实现高覆盖率的测试,以下是示例代码:
#include <stdint.h>
typedef uint8_t Std_ReturnType;
#define RTE_E_OK 0
#define DEM_EVENT_STATUS_PREPASSED 0
#define DEM_EVENT_STATUS_PREFAILED 1
#define RTE_SWC_ADC_ETHDIAG_SWC_INU_LinkUpStatus_u8_Signal 1
typedef struct {
uint8_t inu_LinkUpSts;
uint8_t ccu_LinkUpSts;
} LinkStatus;
Std_ReturnType Rte_Read_SWC_ADC_FM_SWC_INU_LinkUpStatus_u8_Signal(uint8_t* data) {
*data = RTE_SWC_ADC_ETHDIAG_SWC_INU_LinkUpStatus_u8_Signal;
return RTE_E_OK;
}
void Rte_Call_Event_DTC_0xD70188_Event_SetSts(uint8_t status) {
// 添加实际的实现,根据 DEM 事件设置状态的需求
// 此处仅为示例
// ...
}
void EthLinkupStsDTCMainfunction(void) {
uint8_t inu_LinkUpSts, ccu_LinkUpSts;
Rte_Read_SWC_ADC_FM_SWC_INU_LinkUpStatus_u8_Signal(&inu_LinkUpSts);
if (inu_LinkUpSts != 1) {
/* 1inuDown */
Rte_Call_Event_DTC_0xD70188_Event_SetSts(DEM_EVENT_STATUS_PREFAILED);
} else {
Rte_Call_Event_DTC_0xD70188_Event_SetSts(DEM_EVENT_STATUS_PREPASSED);
}
}
int main(void) {
/* 空的 main 函数 */
return 0;
}
接下来,我们以函数EthLinkupStsDTCMainfunction为例,用Pasasoft进行测试,在默认未配置函数打桩的情况下,其测试结果覆盖情况如下图:

测试用例设计
对被调函数Rte_Read_SWC_ADC_FM_SWC_INU_LinkUpStatus_u8_Signal打桩,因为Rte_Read_SWC_ADC_FM_SWC_INU_LinkUpStatus_u8_Signal的逻辑中,其实就是对inu_LinkUpSts重新赋值了。
Testcase1:对Rte_Read_SWC_ADC_FM_SWC_INU_LinkUpStatus_u8_Signal打桩,将inu_LinkUpSts的值修改成不等于1的值,来满足 line31 的条件。
Testcase2:对Rte_Read_SWC_ADC_FM_SWC_INU_LinkUpStatus_u8_Signal打桩,将inu_LinkUpSts的值修改成等于1的值,来满足 line34 的条件。
桩函数代码如下:
#include "cpptest.h"
#include <stdint.h>
typedef uint8_t Std_ReturnType;
/**
* This file contains user stub definitions.
*
* To create a user stub:
* 1. Open stub template list:
* - Eclipse IDE: type 'stub' and press <Ctrl> <Space>
* - Microsoft Visual Studio IDE: use context menu C++test->Insert Snippet...
* 2. Choose the stub template from the list.
* 3. #include the header file where the function you want to stub is originally
* declared as well as any supporting header files as necessary.
* 4. Fill out the stub signature to match that of the original function,
* while keeping the CppTest_Stub prefix when it applies.
* Note: for C++ operators, use appropriate stub names - e.g.:
* CppTest_Stub_operator_new for operator new
* CppTest_Stub_operator_delete for operator delete
* CppTest_Stub_operator_plus for operator +
* Refer to C++test User's Guide for a complete list of stub names for operators.
* 5. Fill out the body of the stub according to intent.
*
* Available C++test API functions (see C++test Users Guide for details):
* void CppTest_Assert(bool test, const char * message)
* void CppTest_Break()
* const char* CppTest_GetCurrentTestCaseName()
* const char* CppTest_GetCurrentTestSuiteName()
* bool CppTest_IsCurrentTestCase(const char* testCaseName)
*/
/**
* Header files where the stubbed functions are originally declared.
* Verify #include directives and add any additional header files as necessary.
*/
/** User stub definition for function: Std_ReturnType Rte_Read_SWC_ADC_FM_SWC_INU_LinkUpStatus_u8_Signal(uint8_t *) */
EXTERN_C_LINKAGE Std_ReturnType Rte_Read_SWC_ADC_FM_SWC_INU_LinkUpStatus_u8_Signal (uint8_t * data) ;
EXTERN_C_LINKAGE Std_ReturnType CppTest_Stub_Rte_Read_SWC_ADC_FM_SWC_INU_LinkUpStatus_u8_Signal (uint8_t * data)
{
CPPTEST_STUB_CALLED("Rte_Read_SWC_ADC_FM_SWC_INU_LinkUpStatus_u8_Signal");
Std_ReturnType __return = (unsigned char)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, Std_ReturnType* __return, uint8_t * data)
*
* 2. Register stub callback in test case function - use the following code:
* CPPTEST_REGISTER_STUB_CALLBACK("Rte_Read_SWC_ADC_FM_SWC_INU_LinkUpStatus_u8_Signal", &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 = Rte_Read_SWC_ADC_FM_SWC_INU_LinkUpStatus_u8_Signal(data);
*/
if (CPPTEST_STUB_HAS_CALLBACK()) {
CPPTEST_STUB_CALLBACK_PARAMS(Std_ReturnType* __return, uint8_t * data);
CPPTEST_STUB_INVOKE_CALLBACK(&__return, data);
} else {
if(CppTest_IsCurrentTestCase("TestSuite_main_c_136bf872_test_EthLinkupStsDTCMainfunction_1"))
{
*data = 1;
}
else
{
*data = 2;
}
}
return __return;
}
运行用例后,我们可以在Parasoft C/C++test清楚的看到我们使用桩函数的方式,来控制输入参数后覆盖率结果,和未使用的相比,有大幅度的提升。

Parasoft 通过其强大的桩函数功能,使开发人员能够轻松模拟外部依赖并精准控制输入参数,从而高效完成对主函数各条件分支的全面测试,将难以触发的测试场景变得完全可控。这不仅显著提升了单元测试的效率和代码可靠性,更是实现高覆盖率目标的关键技术。Parasoft 提供了一整套贯穿软件开发生命周期的自动化测试解决方案,致力于在代码质量、功能安全及行业合规性方面为客户提供全面保障,帮助团队应对复杂交互场景的测试挑战,最终确保软件产品符合高质量标准与严格的安全规范。
关于慧都
慧都是一家行业数字化解决方案公司,专注于软件、石油与工业领域,以深入的业务理解和行业经验,帮助企业实现智能化转型与持续竞争优势。在软件工程领域,我们提供开发控件、研发管理、代码开发、部署运维等软件开发全链路所需的产品,提供正版授权采购、技术选型、个性化维保等服务,帮助客户实现技术合规、降本增效与风险可控。
慧都科技是 Parasoft 公司在中国区的官方授权合作伙伴。为国内企业提供 Parasoft 软件测试工具的正版授权销售、技术支持、定制化部署及实施服务,旨在帮助国内企业提升软件质量与测试效率。
023-68661681
返回
发表评论