关于对汽车ECU软件测试的理解

2021-12-04 19:42:01·  来源:汽车ECU开发  作者:木城  
 
在汽车行业对软件开发重视的当下,不少从其他行业加入的,那熟悉ECU软件测试流程就是必要的了,另外对于一直在行业深耕的开发或测试人员,梳理一下测试流程也是
在汽车行业对软件开发重视的当下,不少从其他行业加入的,那熟悉ECU软件测试流程就是必要的了,另外对于一直在行业深耕的开发或测试人员,梳理一下测试流程也是有必要的。
接下来我们以常用的V模型开发流程为线索,列举实例来说明。
图1. V型开发流程
01.
需求编写

假如现在我写了一个系统需求,也就是图1中的“Technical Safety Concept”:
(PS:所有的Techincal Safety Concept都是系统级需求,不是软件需求)
系统需求:
自适应巡航功能只能在30公里到120公里每小时之间激活.[ACC-SysReq 001];
并且一旦退出后不可再自动激活[ACC-SysReq 002]。
简单起见,我们先看第一条需求,并把这条系统需求写成软件需求:
软件需求:
当以下条件满足时,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{ }
有同学可能会好奇,第一个if语句写完了直接写else不就完了嘛。
是的, 但是目前我也不知道客户后面会怎么改这个需求,可能会对其他速度段增加新的状态,所以就先写个else if在这里,方便以后扩展。
到这,V模型的左半边我们就做完了,现在我们开始来测试。

02.
单元测试
写完代码并编译成功后,先进行代码的单元测试,图1 V模型中的“Software Unit Verification”。顾名思义,就是把新编写或者修改过的单元(单独的C文件,在本例中是上述的acc.c)与整个软件工程隔离,单独测试其输入输出。


图2. 单元测试只关心某个具体的软件单元

汽车上的代码开发通常首先要做MISRA-C规则测试。MISRA-C测试是一种代码静态测试,用来检验编码是否符合一系列预先设定的编程规则。这里我们假设用的测试工具是QAC。
就我写的这段代码,估计会报出一个warning, 因为 “else” 这个分枝实际上是无法触发的,而MISRA-C的其中一个规则就是所有代码都必须可触发,所谓“Accessible”。当然啦,这里我是有意为之,所以可以注释一下就放过去了。
下一个步还可以进行Polyspace测试,Polyspace也是一种静态测试工具,其可以进一步帮助判断算法运算过程中,会不会产生诸如数组索引越界、被除数为零之类的bug 。上述例子中只有逻辑判断,所以其实不需要做Polyspace测试。
接下来进行功能测试。在功能测试中,我们需要:
  1. 梳理待测单元的输入和输出信号
  2. 设计一系列的输入信号值,并同时列举对应的正确输出信号值。我们把这个叫做“测试集”。
  3. 输入测试集中的输入信号值,运行单元代码。如果输出信号的值和测试集中的正确输出信号值相同,则功能测试通过。
编写测试集的基本原则之一为测试需覆盖所有代码,并且尽量测试所有判断逻辑。上述例子非常简单,只有一个输入变量和一个输出变量,分别为 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等。

03.
软件集成测试
完成单元测试后,就要把测试好的软件单元集成到整个软件工程里来测试。这一步对应图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)。

04.
硬件在环测试(HIL)
完成SIL测试后,下面就是硬件在环测试了(Hardware in the loop, HIL),对应了图1中的 “Testing of embedded software”。有一些企业在硬件在环测试前之还会进行PIL测试(Processor in the loop),这里就不讨论了。
HIL测试也是一种集成测试。前面讨论的软件集成测试,是在PC 仿真环境执行的,而实际ECU无论是负载、内存、硬件等方面和PC环境有很大的不同,所以相同的功能需要在实际硬件中再测试一遍。
也就是说,HIL测试与软件集成测试最大的不同在于,前者运行于实际硬件中,而后者只是运行在计算机仿真环境下。
硬件在环测试的主要工具是实际的零部件。比如测试ACC功能的话可以是ADAS控制器,或者是集成了ACC功能的毫米波雷达、摄像头等。除此之外还要有一个实验台架提供必要的运行环境、电力供应和总线接口。
常用的HIL测试工具比如dspace的测试环境,dspace control desk。
和软件集成测试一样,HIL测试也是通过改变原始的CAN信号(上述中的WheelSpdRaw)来进行测试,只不过,这一次不是直接改变WheelSpdRaw在内存中的数值,而是通过HIL测试台架真的向ECU通过CAN发送真实的WheelSpdRaw信号。
HIL测试的测试集,也就是测试用例需要和软件需求Software Requirement 严格对应,可以是一对一,一对多或者多对一都可以。所有的 HIL测试用例都必须根据一条对应的Software Requirement 写出,但是条件就没有单元测试时候那么苛刻了。
比如为了测试需求ACC-Req 001,HIL测试用例可以写成:
  1. Turn ECU on;
  2. Set all wheel speed at 0;
  3. Turn ACC function on;
  4. Observe ACC status to be SUPPRESSED;
  5. Gradually increase all wheel speed to 31 kph;
  6. Observe ACC status change to READY after 30 kph;
  7. Gradually increase all wheel speed to 121 kph;
  8. Observe ACC status change to SUPPRESSED;
  9. Gradually decrease all wheel speed to 119 kph;
  10. Observe ACC status change to READY below 120 kph;
  11. Gradually decrease all wheel speed to 29 kph;
  12. Observe ACC status change to SUPPRESSED;
  13. Turn ECU off.
需要把trigger和recover的情况都覆盖到。事实上这个测试用例也可以用来测试ACC-Req 002,这就是“一对多”的情况。
05.
实车测试
实车测试就很好理解了,在所有前述测试都通过以后,工程师上车来实际测试相关功能。这对应了图1中的“System and item integration and testing”。实车测试用例需要根据系统需求来制定。
对于本文的例子,可以写成:
1.着车后打开ACC功能,保持车辆静止。观察仪表盘,ACC 功能未启动。
2. 将汽车加速至30kph,再次打开ACC 功能, 观察仪表盘,ACC启动。将汽车减速至29kph,观察仪表盘,ACC 功能退出。
3. 将汽车加速至110 kph, 打开ACC 功能, 观察仪表盘, ACC 启动。将汽车加速到121kph,观察仪表盘,ACC 功能退出。
分享到:
 
反对 0 举报 0 收藏 0 评论 0
沪ICP备11026620号