利用静态检查工具完善功能安全中测试覆盖率
在功能安全中测试覆盖率是比较重要的概念,也是在验证过程中通常需要花费时间较多的步骤,如果能借助于静态检查工具的死逻辑查找和声明、测试用例自动补全等功能往往能取得事半功倍的效果。功能安全标准中常见的几种覆盖率类型有:
- 语句覆盖:程序中的每条语句是否都被执行到。
- 判定覆盖(决策覆盖):各分支路径是否都被执行到。
- 条件覆盖:进入分支前的判断条件中的各子条件的可能输出是否都满足到。
- 修正条件判定覆盖(MC/DC):每个能独立影响到决策输出的条件是否都被满足到。MC/DC 其实是条件组合覆盖的子集,条件组合覆盖要求覆盖判定中所有条件取值的所有可能组合,所需测试用例和条件数成指数关系,在实际应用中难以操作。MC/DC 具有条件组合覆盖的优势,同时大幅减少用例数。比如对于判定条件 X||(Y&&Z), MC/DC 通过下表的四个测试用例即可实现 100% 覆盖,而如果采用条件组合覆盖则需要8个测试用例,随着条件数的增加用例数的差异会更加明显。
在采用基于模型设计时,语句覆盖对等的概念是执行覆盖,意指模型中的每个基本模块在仿真过程中是否都被运行到。判定覆盖、条件覆盖和 MC/DC 在模型层面均有类似的概念。
函数覆盖和函数调用覆盖
函数是程序的基本组成部分,程序通过调用函数实现功能,同一函数可能会被多次调用。如果所有定义的函数均被执行到,则满足函数覆盖;如果程序中的所有函数调用处(包括同一函数的多次调用)均被执行到,则满足函数调用覆盖。函数覆盖和函数调用覆盖只针对代码,对于模型则没有对应概念。在基于模型设计中,我们可以借助于软件在环(SIL)测试来获取这一指标。
单元级与架构级覆盖率要求
在 ISO 26262:2018 中覆盖率要求在单元级和架构级是不一样的,因此如何合理划分单元是非常重要的。
覆盖率与死逻辑
在静态检查中有一项是检查程序中有无不可达代码(死逻辑),但并不能替代测试覆盖率。没有不可达代码意味着有 100% 测试覆盖的可能,后续还需要通过运行测试用例并收集到覆盖率数据;有不可达代码意味着从理论上无法通过测试达到 100% 覆盖。
利用代码检查完善覆盖率测试
在实践中我们可以利用静态检查的这个能力来辅助测试覆盖率,从而发现程序中的缺陷或者加以声明(Justification)。以代码静态检查和形式化验证能力见长的 Polyspace 在 R2023b 之后增加了动态测试工具 Polyspace Test, 我们可以从以下案例中来看两者是如何相辅相成实现测试覆盖率和声明的。
首先利用代码解析功能查看程序中所涉及的头文件、函数和数据类型,在函数调用图中理解函数调用的层次关系。
在设计测试用例时可以与对应的需求进行链接,在编译前选择获取代码覆盖率。
从收集的覆盖率数据看到语句和决策覆盖尚未满足,也可以进一步分析具体的覆盖点。
将已有的覆盖率数据作为输入并借助于自动生成测试功能,再次运行包括新增的生成用例在内的所有用例,覆盖率数据有明显提升,尚未达到的决策覆盖很有可能是不可达代码。
我们可以借助集成的静态检查和形式化验证功能分析并定位到具体的不可达代码处,通过代码审查排查代码缺陷或者将静态检查结果导入到覆盖分析中作为声明。
以上从工具的角度展示了如何利用静态检查和形式化验证的能力来完善测试覆盖率的过程,具体的使用方法需要根据代码的安全要求和质量目标所定的流程来开展。