当前位置:首页 > 科研成果库

测试性设计:别等到炸了才想起它

2026-08-07 01:08:03小研科研成果库9

前几天翻旧硬盘,找到一份十年前的项目文档——一个智能电表方案,硬件画得精美,软件架构图能挂卢浮宫。可测试方案那页就一行字:‘功能测试,由开发人员自行完成。’我愣了半天,然后笑了。这他妈不就是当年我带着实习生干的事吗?板子回来,上电,冒烟,一群人围着示波器抓耳挠腮,最后发现一个贴片电容焊反了。说实话,那次炸掉的不仅是电容,还有我对‘设计完成度’的信仰。

测试性设计,Design for Testability,DFT。听起来像是一个冰冷枯燥的工程术语。但你要是真被失控的产线、诡异的现场故障、或者永远修不好的代码折磨过——你会明白这玩意儿简直就是一种仁慈。只可惜,大部分人都要在交过惨痛学费后才懂。

不过话说回来,DFT 不是玄学。它是一套你从第一天就该埋进产品骨子里的机制,而不是等 bug 扎堆后打的补丁。

硬件佬的血泪:为什么测试点不是摆设?

PCB 上那些亮晶晶的小圆点,密密麻麻,布局工程师经常嫌弃它们破坏美感。我认识一位老工程师,外号‘焊武帝’,他画板有个怪癖:所有关键信号必须拉测试点,而且间隔严格卡在 2.54mm,方便排针一插就测。我们笑他迂,直到有一次电源模块间歇性震荡,老哥用逻辑分析仪两分钟定位到一颗虚焊的 0402 电阻,而我们都快把板子烤焦了。

——这就是物理可及性。听起来简单,但在高密度互连(HDI)、埋盲孔满天飞的今天,留出测试点是真的肉疼。面积、成本、信号完整性,全是借口。可你有没有想过,一个没有测试点的 BGA 封装芯片,出了问题就等于黑洞。边界扫描(Boundary Scan,IEEE 1149.1 标准)就是从这种绝望中长出来的智慧。它让你在芯片管脚上虚拟出一圈‘探头’,不碰物理 pin 也能读写逻辑电平。你知道在航空电子设备里,DFT 合规是强制项吗?因为谁也不想在万米高空靠猜来排故。

高密度PCB边界扫描测试点布局图高密度PCB边界扫描测试点布局图

我记得 2017 年左右,国内一家做 FPGA 加速卡的创业团队,产品在数据中心批量上架后开始随机丢包。没有 DFT,没有边界扫描,他们唯一的手段就是拆机、换卡、祈祷。最后发现是某个 SerDes 通道的参考时钟在特定温度下漂移,根源在于电源纹波耦合。他们后来重新设计时,不仅加了详细的电源监测测试点,甚至用 CPLD 做了一个微型内建自测试(BIST)引擎。你看,学费交够了,自然就乖了。

软件测试性:别指望全栈能救你

软件界有个迷思:代码写得优雅,测试自然简单。呸。我见过最优雅的代码是俄罗斯套娃式的抽象层,一层套一层,层与层之间用依赖注入搞得云里雾里。跑起来是挺美的,但想单独测某个中间层——对不起,你得拉起来一整套容器环境,再 mock 掉八个外部服务。这叫什么测试性?这叫绑架。

真正的软件测试性,是让你的模块能够被单元测试‘秒插’。就像 USB 外设那样即插即用,而不是像老式磁带机得绕半天。

举个例子,前阵子帮朋友看一个智能家居网关的代码,核心逻辑和 MQTT 协议栈死死绑在一起。想测逻辑?必须连上真实 broker。我建议他把协议适配层抽出来,用接口隔离,这样测试时注入一个假 broker 就行。他花了一周重构,然后发消息说:‘我现在打一个命令就跑完全部测试,以前得折腾半小时。’对,那种快感,只有被折磨过的人才懂。

还有可观测性——很多人觉得那是运维的事。错。从设计第一天起,你就该问:如果这段代码在生产环境陷入死锁,我需要看到什么才能定位?日志、指标、追踪,不是运维三板斧,而是你用代码写下的‘测试遗嘱’。我曾经在一个高并发交易系统里埋下了一个不起眼的计数器,记录某个锁的争抢次数。上线后流量一压,它疯狂告警,我们才发现数据库连接池有个边界条件 bug。没有那个埋点,估计得回滚到半夜。

微服务架构可观测性测试点示意图微服务架构可观测性测试点示意图

内建自测试:让系统学会‘自己检查作业’

内建自测试:让系统学会‘自己检查作业’内建自测试:让系统学会‘自己检查作业’

芯片行业对 BIST(Built-In Self-Test)的痴迷是有道理的。量产测试时,自动测试设备(ATE)贵得离谱,时间就是钱。于是工程师们把测试电路塞进芯片里,让它自己生成激励、自己比对签名。听起来完美?代价是面积冗余,还有可怕的验证复杂度——你得保证 BIST 电路本身没 bug,否则就是请个庸医随身带刀。

但 BIST 的哲学早就溢出半导体了。我记得某款工业机器人,每次上电都会运行一段‘机械自检舞’:所有关节低速全范围运动,编码器回读比对。如果发现偏差超阈值,直接锁死报修。这就是机械 BIST。还有一次跟一家做自动驾驶域控制器的团队聊天,他们的板子有个硬件安全模块(HSM),每次启机都会对关键固件做完整性校验,用的是 CRC 核,硬逻辑跑的。这种设计,就是把‘信不过任何人’写进了基因里。

不过话说回来,过度设计也是坑。我见过一个项目,在每一路 ADC 输入都加了诊断电路,能区分开路、短路、漏电——听起来很厉害,结果 BOM 成本涨了 15%,而且诊断逻辑本身消耗的固件资源差点把主控拖死。最后被砍掉一半,只保留致命故障检测。所以,DFT 的本质是风险权衡,不是功能堆砌。

最近有一个趋势很有意思:数字孪生结合 DFT。你在虚拟样机里注入故障,观察数字孪生的测试覆盖率和响应。这在风电变流器、医疗 CT 机这些停机成本巨大的设备上已经落地。一家北欧公司甚至公开了他们的故障注入框架,用 Rust 写的,号称每秒能注入 2000 个瞬态错误——我试了一下,差点把仿真服务器跑冒烟,但确实找到了一个隐藏了八年的看门狗逻辑漏洞。这让我挺感慨的:很多时候,我们不是不知道 DFT 重要,而是缺少那种‘刻意破坏’的勇气。

所以下次画板子、写代码、搭架构的时候,不妨多问一句:如果这个玩意儿最后要交给一个暴躁的维修工,或者半夜三点被报警电话吵醒的我,我会希望设计者当初做了什么?答案,往往就是测试性设计该落脚的地方。