在汽车行业对软件开发重视的当下,不少从其他行业加入的,那熟悉ECU软件测试流程就是必要的了,另外对于一直在行业深耕的开发或测试人员,梳理一下测试流程也是有必要的。
接下来我们以常用的V模型开发流程为线索,列举实例来说明。
01.
需求编写
软件需求:
当以下条件满足时,ACC功能状态设置为READY[ACC-Req 001]:
车速大于或等于30kph AND
车速小于或等于120kph.
当满足以下条件时,ACC功能状态设置为SUPPRESSED[ACC-Req 002]:
车速小于30kph OR
车速大于120kph.
在软件设计文档中, 也就是图1V模型中的Architectual Design里可以写:
Design Requirement
Acc_ActSt shall equal to READY if:
SafeVehSpd is greater or equal to 30kph AND
SafeVehSpd is less than or equal to 120kph.
Acc_ActSt shall equal to SUPPRESSEDif:
SafeVehSpd is less than 30kph OR
SafeVehSpd is greater than 120kph.
到这里,以上就是一个最简单的需求demo。根据这个需求,你通过几行代码来实现。假设使用C来写,在原有的C文件acc.c中加入了:
if((SafeVehSpd >= 30) && (SafeVehSpd <= 120)){
Acc_ActSt = READY;
}
else if((SafeVehSpd < 30) || (SafeVehSpd > 120)){
Acc_ActSt = SUPPRESSED;
}
else{
}
是的, 但是目前我也不知道客户后面会怎么改这个需求,可能会对其他速度段增加新的状态,所以就先写个else if在这里,方便以后扩展。
到这,V模型的左半边我们就做完了,现在我们开始来测试。
写完代码并编译成功后,先进行代码的单元测试,图1 V模型中的“Software Unit Verification”。顾名思义,就是把新编写或者修改过的单元(单独的C文件,在本例中是上述的acc.c)与整个软件工程隔离,单独测试其输入输出。
图2. 单元测试只关心某个具体的软件单元
就我写的这段代码,估计会报出一个warning, 因为 “else” 这个分枝实际上是无法触发的,而MISRA-C的其中一个规则就是所有代码都必须可触发,所谓“Accessible”。当然啦,这里我是有意为之,所以可以注释一下就放过去了。
下一个步还可以进行Polyspace测试,Polyspace也是一种静态测试工具,其可以进一步帮助判断算法运算过程中,会不会产生诸如数组索引越界、被除数为零之类的bug 。上述例子中只有逻辑判断,所以其实不需要做Polyspace测试。
接下来进行功能测试。在功能测试中,我们需要:
梳理待测单元的输入和输出信号
设计一系列的输入信号值,并同时列举对应的正确输出信号值。我们把这个叫做“测试集”。
输入测试集中的输入信号值,运行单元代码。如果输出信号的值和测试集中的正确输出信号值相同,则功能测试通过。
编写测试集的基本原则之一为测试需覆盖所有代码,并且尽量测试所有判断逻辑。上述例子非常简单,只有一个输入变量和一个输出变量,分别为 SafeVehSpd 和Acc_ActSt。
我们需要把输入信号按判断逻辑分成若干个Equivalent Class 。在上述例子中,将输入信号(假设 SafeVehSpd的类型为Unsigned int, 速度上限为500 kph)SafeVehSpd分成三个Equivalent Class,分别为:
1. [0, 30)
2. [30, 120]
3. (120,500]
于是这三个Equivalent Class里随机各取一个值,就能测试所有代码逻辑了。但实际测试中,往往还需进一步进行边界测试, 也就取每个Equivalent Class的两端的值来进行测试。这就涉及到精度问题了。假设这段代码是定点运算,车速数值由10bit表示,前述车速上限为500,车速的精度就是 500/(2^10)= 0.48828125。
所以严格来说,测试集需要测试的输入变量SafeVehSpd的值有6个,分别是 0 ,29.5117188 ,30 , 120 , 120.48828125 , 500 。
当然,现在很多工具支持自动生成测试集,所以不用程序员费劲的去算这些破玩意儿。
需要说明的是,就算进行了完善的功能测试,也并不能保证功能就没有bug,因为实际工程中输入信号的组合是无穷无尽的,再加上时序等因素,功能测试不可能穷尽所有的实际情况,我们只是尽力而为。
汽车行业比较流行的单元测试工具有VectorCAST、Cantata等。
完成单元测试后,就要把测试好的软件单元集成到整个软件工程里来测试。这一步对应图1中的“software verification and integration"。
图3.集成测试关注整个系统的输入输出
在单元测试中,我们通过直接改变SafeVehSpd 的值来进行测试。实际上,SafeVehSpd来自CAN总线上的车轮轮速数据。
假设如图3所示,获取CAN总线上传来的原始轮速信号WheelSpdRaw, 经过通信接口模块COM_IF.c处理 以及车速计算模块VehSpd.c计算后 ,得到信号SafeVehSpd 。那么在集成测试中,我们通过改变WheelSpdRaw的数值来对acc.c中的代码进行测试。为了其目的是为了验证acc.c模块与其他模块的接口是否正确,以及各模块之间是否有冲突。
进行软件集成测试的时候,图3的三个模块其实合并在了一起形成了一个“黑盒”,我们只关心最初的输入信号WheelSpdRaw 和最终的输出信号Acc_ActSt 之间的逻辑。
在实际工程中,COM_IF.c、VehSpd.c 和 Acc.c 三个模块很可能是由三个工程师维护的,这就可能导致任何一个模块单独进行集成测试都通过不了。这时候就需要由项目经理或者product owner提前进行沟通协调,确保所有功能都更新以后,三个模块一起进行集成测试。
软件集成测试流行的工具和单元测试一样, 也是Cantata之类的。
软件单元测试和软件集成测试都可以被称为软件在环测试(Software in the loop , SIL)。
后台回复“汽车ECU开发001”获取CANoe.Diva操作指南及2021年全球半导体研究报告。
阅读原文,关注作者知乎
特斯拉最新的12V蓄电池有什么不同?
特斯拉最新中央计算模块(CCM)解析
2021款特斯拉Model Y ECU接口梳理
详解CANoe之CAPL编程
关于CAN时间同步的理解
dbc文件的格式以及创建详解
大众ID.4 X网络架构详解
基于UDS的Bootloder详解
关于整车上下电流程的理解
一文详解CAN总线错误帧|附下载
DoIP协议介绍,资料分享!
详解车载网络 OTA系统的开发|文末附下载
一文了解汽车嵌入式AUTOSAR架构|附下载
特斯拉Autopilot系统安全研究|附dbc下载