单元测试桩写到手软?Parasoft 的桩生成技巧值得一学

2026-10-11

做单元测试的人,大概都经历过这样的崩溃时刻:终于下定决心给一个模块补测试,打开代码一看,这个函数调了数据库,那个函数读了配置文件,还有个兄弟直接操作了硬件寄存器。

测个锤子啊。

于是桩(stub)就成了单元测试绕不开的话题。所谓打桩,就是把这些"不听话"的依赖替换成你自己控制的假实现——数据库不连了,返回个固定值;硬件不碰了,模拟一个寄存器。这样测试才能聚焦到被测函数本身的逻辑上。

问题是,手工写桩是真的烦。我见过一个工程,几百个桩函数全是同事一个一个敲的,光维护这些桩就占了他将近三分之一的工作量。

C/C++test 的自动打桩是什么体验

Parasoft C/C++test 里有个功能我一直很喜欢:自动桩生成。

它的原理不复杂——分析被测代码的链接关系,找出所有外部依赖,然后自动生成桩框架。你在测试用例里只需要关心一件事:这个桩在被调用时应该返回什么。

举个实际点的例子。假设有个函数 `check_battery_status()`,内部调用了 `read_adc()` 去读硬件。自动生成的桩会替你把 `read_adc()` 隔离掉,你在测试里写一行"当 read_adc 被调用时返回 512",就能模拟出"电池电压正常"的场景。想测低电量告警?把返回值改成 50 就行。

同一个函数,十几条测试路径,全靠控制桩的返回值来铺开。这在手工时代得写一堆条件编译或者函数指针才能实现。

几个实战里摸出来的技巧

光会自动生成还不够,分享几个我们踩坑之后总结的经验。

第一,别迷信全自动。 自动桩的逻辑骨架是好的,但桩的行为默认很"呆"——要么返回零值,要么什么都不做。关键路径上的桩,一定要人工设定返回值和分支行为。我们的习惯是:自动生成之后,用 grep 扫一遍所有桩,标出哪些是"有实际逻辑"的桩,逐个补行为。

第二,桩的状态要可控。 有些函数会被调用多次,每次要返回不同的值。比如重试逻辑,前两次失败第三次成功。C/C++test 支持在桩里记录调用次数并按次序返回不同结果,用好这个特性,重试、超时、降级这类逻辑都能测到。

第三,警惕"桩测出了假绿灯"。 桩和真实实现的偏差越大,测试结果越失真。有一回我们一个模块单测全绿,集成阶段照样翻车,排查下来是桩的行为和真实驱动对不上。从那以后我们定了条规矩:桩的行为必须有真实接口文档做依据,不能拍脑袋写。

第四,配合覆盖率看桩的效果。 打桩的目的是把测试隔离出来,但如果你发现某个函数的覆盖率上不去,很可能是桩设置得太"顺利"了,把错误分支全屏蔽了。让桩多返回几种异常值,覆盖率往往还能再爬一截。

回归测试里的隐藏价值

桩还有一个容易被忽略的用处:回归测试提速。

全量集成测试跑一轮可能要几个小时,而带桩的单测几分钟就完事。代码改动之后先跑一遍单测,几分钟内就知道有没有把基本逻辑改坏,不用傻等集成环境。我们的流水线就是这么配的,提交代码后先跑单测,单测过了才进集成阶段。DTP 上能看到每次提交的测试结果,哪次改动引入的问题一目了然。

对老项目改造来说,这套打法尤其友好。遗留代码没有测试保护,改一处心惊肉跳;先把桩的框架搭起来,哪怕只有 30% 的覆盖率,也比重构裸奔强太多了。

写在最后

单元测试这件苦差事,桩的维护成本是劝退大多数团队的头号原因。Parasoft C/C++test 的自动桩生成,把这件事从"纯手工"变成了"半自动",剩下的那点人工,花在刀刃上就行。

工具永远是第二位的,第一位的是你得承认:测不了的代码,就是不可控的代码。把桩打好,把测试立起来,晚上才睡得香。

阅读0
分享
写评论...