2. 测试策略制定:基于风险的测试策略、测试覆盖率的定义与目标、测试优先级划分

测试策略这东西,说白了就是回答三个问题:测什么?测多深?先测哪个?

我刚入行那会儿,总觉得测试越多越好,恨不得把所有 corner case 都跑一遍。结果呢?项目周期被拖得死死的,流片节点一推再推。后来我明白了——测试不是做加法,是做减法。你得把有限的资源,砸在最可能出问题的地方。

2.1 基于风险的测试策略

什么叫基于风险?就是问自己:这个模块如果坏了,后果有多严重?它坏掉的可能性有多大?

我习惯把风险分成三个维度来评估:

风险维度 评估要素 典型场景
功能关键性 该功能失效对系统的影响等级 时钟复位、电源管理、安全校验
设计复杂度 逻辑规模、状态机深度、跨时钟域数量 多核一致性协议、DDR控制器
历史缺陷密度 同类型模块在以往项目中的 bug 率 AHB 桥接、FIFO 满空判断

把这三个维度打分,然后画个风险矩阵。高关键性 + 高复杂度 = 红色区域,必须投入最多测试资源。低关键性 + 低复杂度 = 绿色区域,跑个基本功能验证就够了。

核心原则:测试资源永远向高风险区域倾斜。不要试图覆盖所有路径,你覆盖不完的。

我曾经在一个 AI 加速器项目里,团队花了两个月做全芯片的随机验证,结果流片回来发现一个很基础的时钟门控逻辑有问题——那个模块被标记为“低复杂度”,没人认真测。嗯,从那以后,我再也不敢轻视任何“看起来简单”的逻辑了。

2.2 测试覆盖率的定义与目标

覆盖率不是数字游戏。它告诉你:你的测试到底有没有把设计“摸透”。

我一般把覆盖率分成两大类:

  • 代码覆盖率——看你的仿真跑了多少代码行、多少分支、多少状态。
  • 功能覆盖率——看你的测试有没有踩到设计规范里定义的那些“有意思”的场景。

下面这张图是我常用的覆盖率体系框架:

测试覆盖率体系框架 测试覆盖率 代码覆盖率 功能覆盖率 行覆盖率 分支覆盖率 状态机覆盖率 翻转覆盖率 断言覆盖率 交叉覆盖率 过渡覆盖率 组合覆盖率 目标设定建议 代码覆盖率 ≥ 95% | 功能覆盖率 ≥ 90% | 交叉覆盖率 ≥ 85%

你可能会问:覆盖率目标设多少合适?我个人的经验是:

经验阈值:

  • 行覆盖率:95% 以上。剩下的 5% 通常是不可达代码或冗余逻辑。
  • 分支覆盖率:90% 以上。分支没覆盖到的地方,往往是 bug 的温床。
  • 功能覆盖率:90% 以上。重点关注交叉覆盖率和过渡覆盖率。

但记住——100% 覆盖率不代表没有 bug。它只代表你测过的东西没问题,不代表你没测到的东西没问题。

2.3 测试优先级划分

测试优先级怎么排?我有一套自己的“三刀流”方法:

  1. 第一刀:按风险切——高风险模块优先,低风险模块靠后。
  2. 第二刀:按依赖切——被其他模块依赖的模块先测,比如总线、时钟、复位。
  3. 第三刀:按回归成本切——跑得慢的测试用例,放到晚上或周末跑。

举个例子,我在一个 SoC 项目里是这样排的:

优先级 测试内容 执行时机 说明
P0 时钟复位、电源域、DFT 扫描链 每次提交代码后立即执行 这些挂了,后面什么都跑不了
P1 核心功能验证、关键接口协议 每日回归 确保主要功能不倒退
P2 性能测试、功耗场景、随机验证 每周回归 覆盖 corner case 和边界条件
P3 兼容性测试、压力测试、长时运行 里程碑节点前 跑一次可能要几天,不能天天跑

注意:优先级不是一成不变的。随着项目推进,某些 P2 的测试可能会升为 P1。比如,当你发现某个模块的 bug 率突然上升时,就该把它往前挪。

最后说一句:测试策略不是写出来给人看的,是拿来用的。你制定得再漂亮,如果团队不执行,那就是一张废纸。我建议你把策略文档控制在 3 页以内,核心内容用一张图说清楚。剩下的,交给每天的站会和每周的 review。