Cantata做C/C++单元测试时,被测函数经常会调用硬件驱动、通信接口、操作系统函数或其他尚未纳入测试范围的模块。直接把这些真实依赖一起编进测试程序,测试环境会变得很难控制。Cantata可以用Stub模拟外部调用,也可以用Wrapper截获真实函数调用,在测试用例里指定返回值、检查传入参数和控制不同调用次数对应的行为。测试桩已经生成却出现返回值不对、调用次数不匹配或测试程序仍进入真实函数时,可以从桩类型、调用实例和接口定义几个位置查起。
一、Cantata怎么设置测试桩函数
1、生成测试脚本时把外部函数设置为Stub
被测源码已经加入Cantata测试工程后,可以在生成测试脚本时选择哪些依赖使用测试桩。
①在【Project Explorer】中选中准备测试的.c或.cpp文件。
②执行Cantata的测试脚本生成操作,进入【Test Script】配置页面。
③确认【Software Under Test】中已经包含目标源码。
④打开【Stubs and Wrappers】配置区域,查看Cantata从源码调用关系中识别出的外部函数。
⑤找到不准备调用真实实现的函数,将调用控制类型设置为【Stub】。
⑥需要保留真实函数并拦截调用时,改用【Wrapper】,不要和Stub混用。
⑦完成配置后生成【Test Script】。
⑧打开生成的测试脚本,确认对应函数已经出现在受控调用列表中。
Cantata可以自动生成Stub、Isolate和Wrapper。普通外部依赖只需要模拟返回结果时,用Stub就够了;还要进入真实函数并检查调用前后数据时,再考虑Wrapper。
2、给Stub设置返回值和参数检查
测试桩生成以后,还要告诉它每次被调用时返回什么。
①打开生成的【Test Script】。
②进入【Test Case Editor】,选中准备编辑的测试用例。
③找到【Expected Calls】或当前测试用例的受控函数调用区域。
④添加目标Stub函数的调用实例。
⑤在该实例中填写【Expected Parameters】,设置被测函数应该传给Stub的参数值。
⑥函数有返回值时,填写对应【Return Value】。
⑦参数是输出指针时,设置调用后写回的数据。
⑧保存测试用例并重新构建测试脚本。
例如被测函数会调用读取传感器接口,就可以让Stub在某个测试用例中返回成功状态,在另一条用例中返回错误状态,这样不必真的连接硬件也能检查被测代码的不同处理分支。
3、同一个Stub被调用多次时配置多个实例
一个函数在同一测试用例中调用外部接口多次,不能只设置一个返回值就结束。
①在【Test Case Editor】找到目标Stub。
②查看当前测试用例中的【Expected Call Sequence】。
③给第一次调用添加一个Stub实例。
④设置该实例的【Expected Parameters】和【Return Value】。
⑤继续添加第二次、第三次调用实例。
⑥分别设置每次调用需要返回的数据。
⑦调整实例在【Expected Call Sequence】中的顺序。
⑧运行测试,检查实际调用次数和预期顺序是否一致。
Cantata允许同一个受控函数建立多个调用实例,因此可以模拟第一次调用成功、第二次调用超时、第三次恢复这类连续状态。
二、Cantata测试桩调用异常如何处理
1、Stub已经生成但程序仍调用真实函数
这种情况先检查函数到底配置成了Stub还是Wrapper。
①打开【Test Script Editor】。
②进入【Stubs and Wrappers】。
③找到出现问题的函数。
④确认当前类型为【Stub】。
⑤如果设置为【Wrapper】,检查是否选择了继续调用真实对象的行为。
⑥只想模拟函数时,将它改回【Stub】并重新生成测试脚本。
⑦重新执行Build,查看链接日志中是否仍然把真实实现编进测试程序。
如果调用对象位于当前测试边界内部,普通Stub未必适合直接替换,此时可以使用【Wrapper】的替换能力截获调用。
2、出现调用次数或调用顺序不匹配
测试结果提示某个Stub没有按预期调用,可以从调用序列看。
①打开失败的【Test Case】。
②查看【Expected Call Sequence】。
③对照测试结果中的实际调用记录。
④确认Stub预期次数是否和源码实际调用次数一致。
⑤源码只调用一次时,删除多余实例。
⑥源码循环调用三次时,补齐三个调用实例,或者按当前测试方式配置对应循环调用关系。
⑦多个Stub之间存在固定先后顺序时,重新排列【Expected Call Sequence】。
⑧不要求固定顺序的调用,不要误设成严格顺序检查。
源码修改以后,函数调用次数发生变化,旧测试用例里的Expected Call Sequence也要跟着调整。
3、Stub返回值设置了但被测函数拿到的数据不对
返回值正常填写,实际结果却不一致时,要检查函数接口和输出数据。
①确认Stub函数声明与原函数原型一致。
②检查【Return Value】的数据类型。
③函数通过指针返回数据时,不要只设置函数返回值。
④找到对应输出参数,在Stub实例中填写调用后的数据。
⑤结构体指针要检查成员值是否已经设置。
⑥数组参数要核对长度和元素内容。
⑦函数声明近期修改过时,重新解析源码并生成Stub定义。
⑧重新打开测试用例,检查旧实例有没有继续沿用修改前的参数结构。
这类问题在接口从普通参数改成指针、结构体成员发生变化后比较容易出现。
三、测试桩反复报错怎么继续检查
1、检查Stub和真实对象是否同时参与链接
如果构建阶段出现重复符号或链接冲突,可以直接查看编译输出。
①执行当前【Test Script】的Build。
②打开【Console】。
③查找duplicate symbol、multiple definition或类似链接错误。
④确认对应真实源码是否已经加入测试构建。
⑤当前函数准备使用Stub时,把不需要的真实实现移出测试边界。
⑥必须保留真实实现时,改用【Wrapper】处理调用。
⑦重新Build,确认重复定义已经消失。
2、调用接口修改后重新生成受控函数
开发代码换过版本后,原测试脚本里的Stub可能已经和新接口对不上。
①检查当前被测源码中的函数声明。
②对比测试脚本中的Stub参数列表。
③函数新增参数、修改类型或调整返回值后,重新解析测试源码。
④在【Stubs and Wrappers】中重新确认调用类型。
⑤更新对应Stub实例。
⑥重新填写【Expected Parameters】和【Return Value】。
⑦检查【Expected Call Sequence】后再执行测试。
不要只靠手工修改一两个参数继续使用旧Stub,接口变化较大时重新生成受控调用更容易发现遗漏项。
3、用Wrapper检查难以确认的调用
遇到调用已经发生,却判断不清实际传了什么数据,可以暂时改成Wrapper观察。
①在【Stubs and Wrappers】中选择目标函数。
②将调用控制方式设为【Wrapper】。
③生成包含【BEFORE】【REPLACE】【AFTER】控制段的测试脚本。
④需要检查真实输入时,在【BEFORE】阶段记录或验证参数。
⑤需要完全替换实际调用时使用【REPLACE】。
⑥需要检查真实函数执行后的输出时使用【AFTER】。
⑦运行测试,对照实际参数和测试用例中的预期数据。
Cantata的Wrapper可以截获被测代码内部或外部调用,也能按不同调用实例检查参数、返回值和调用顺序。Stub难以说明问题时,用Wrapper查看真实调用过程会更直观。
总结
Cantata测试桩适合把外部依赖从单元测试中拆开,让每条测试用例自己决定外部函数返回什么、传入参数应该是什么以及调用多少次。桩函数出现异常时,可以围绕调用类型、接口定义、实例数量和调用顺序检查,避免把测试环境问题误判成被测代码错误。接口发生修改后同步更新测试脚本,也能减少旧Stub继续影响后续回归测试。如需进一步了解Cantata测试桩配置、Wrapper调用控制与单元测试异常排查,欢迎联系咨询。