1. 诊断自动化测试的工程困局与破局思路
做过ECU诊断测试的同行大概都有类似的体会:一个项目动辄几十上百个诊断服务,每个服务又有不同的会话状态、安全等级、寻址方式,手工点一遍下来少说大半天,遇到版本迭代还得从头再来。更头疼的是,测试用例写在Excel里,执行靠人肉,结果记录靠截图,出了问题回溯起来像考古。这种模式下,测试覆盖率上不去,回归效率极低,而且不同人执行的结果一致性很难保证。
CANoe.DiVa这套工具组合,本质上就是冲着这个痛点来的。它的核心逻辑是:把诊断描述文件(CDD/ODX)作为唯一数据源,自动生成诊断测试用例,然后在CANoe环境中批量执行,最终输出一份带通过/失败判定的测试报告。整个过程不需要你手写一行CAPL代码来构造诊断请求,工具会根据CDD里定义的诊断服务、数据标识符、例程、故障码等对象,自动派生出边界值测试、会话依赖测试、安全访问测试等用例。
这套流程适合谁?如果你是OEM的诊断测试工程师,需要做ECU诊断规范的符合性验证;如果你是Tier1的软件测试人员,需要在每次软件刷写后跑一遍诊断回归;或者你是刚接触UDS诊断的新人,想快速理解诊断服务的交互逻辑,CANoe.DiVa都能给你一条从CDD到测试报告的完整路径。前提是你手头得有CANoe完整 license(DiVa是独立选件)、一个待测ECU或者仿真节点、以及一份像样的CDD文件。
我见过太多人卡在第一步——CDD文件本身就有问题,导致DiVa生成的用例跑不通,然后开始怀疑工具、怀疑ECU、怀疑人生。所以这篇东西我会从CDD的制作要点讲起,把DiVa的配置、执行、报告解读串起来,中间穿插一些我踩过的坑和实际项目里总结出来的技巧。目标很明确:让你看完能自己搭一套能跑通的诊断自动化测试流程。
2. CDD文件:诊断自动化测试的地基
2.1 CDD到底描述了什么
CDD全称CANdela Diagnostic Description,是Vector工具链里用来描述ECU诊断能力的标准格式文件。你可以把它理解成一份“诊断服务说明书”,里面定义了ECU支持哪些UDS服务、每个服务的请求和响应格式、数据标识符的物理意义、故障码的触发条件、安全访问的算法种子等等。
从结构上看,CDD主要包含这几块内容:
- 诊断服务定义:比如0x10会话控制、0x27安全访问、0x22读数据、0x2E写数据、0x31例程控制、0x19读故障码、0x14清除故障码等。每个服务下面会定义子功能、请求参数、正响应格式、负响应码。
- 会话与安全状态机:定义默认会话、编程会话、扩展会话之间的跳转关系,以及安全等级(比如Level 1、Level 2)的解锁条件。
- DID(数据标识符):每个DID对应一个数据对象,包含长度、数据类型、读写权限、所属会话和安全等级。
- RID(例程标识符):用于0x31服务的例程控制,比如自检、擦除、校验等。
- DTC(故障码):故障码编号、故障类型、快照数据、扩展数据、清除条件等。
- 通信参数:诊断请求和响应的CAN ID、寻址方式(物理寻址/功能寻址)、P2/P2*超时时间、S3超时时间等。
DiVa在生成测试用例时,会直接读取这些定义。比如CDD里定义了一个DID只在扩展会话下可读,DiVa就会自动生成一条“在默认会话下读该DID应返回否定响应”的用例。所以CDD的质量直接决定了DiVa测试的覆盖率和准确性。
2.2 制作CDD的常见路径与选型建议
制作CDD一般有三条路:
第一条路:OEM提供标准CDD模板。这是最省事的情况。主机厂通常会给出诊断规范文档和对应的CDD模板,Tier1只需要根据自己ECU的实际实现填充DID、DTC等对象。但现实是,OEM的模板往往只覆盖通用服务,项目特定的DID和例程还是得自己加。
第二条路:从ODX转换。如果项目用的是ODX(Open Diagnostic Data Exchange)格式,可以通过Vector的ODX Converter工具转成CDD。ODX是ISO 22901标准,结构比CDD更复杂,但通用性更好。转换过程中要注意ODX的继承关系和CDD的扁平结构之间的映射,有时候需要手动调整。
第三条路:从零手搓。不推荐,除非你对自己的诊断协议栈了如指掌。手搓CDD最容易犯的错误是会话状态机定义不完整,导致DiVa生成的用例在会话切换时失败。
我的建议是:优先用OEM模板,在此基础上用CANdelaStudio做增量修改。CANdelaStudio是编辑CDD的专用工具,界面虽然不算现代,但功能足够。修改时重点关注三个地方:DID的读写权限和会话依赖、DTC的清除条件、安全访问的算法配置。
2.3 CDD制作中的关键细节与避坑点
DID的数据类型和长度必须和ECU实现一致。我遇到过CDD里定义DID长度为2字节,但ECU实际返回4字节的情况,DiVa执行时直接报长度不匹配。这种问题在手工测试时可能被忽略(因为人眼能看懂),但自动化测试会严格校验。
会话状态机的完整性。CDD里要明确定义每个会话下哪些服务可用、哪些DID可读。如果漏定义了某个会话,DiVa可能不会生成对应的测试用例,导致覆盖率缺口。建议在CANdelaStudio里用状态图视图检查一遍,确保所有会话跳转路径都覆盖到了。
安全访问的种子和密钥算法。如果ECU的安全访问算法是固定的(比如异或运算),可以直接在CDD里配置。如果是动态算法(比如基于随机数),需要提供DLL或者CAPL实现。DiVa在执行安全访问测试时,会调用这个算法来生成密钥。这里有个坑:算法DLL的接口必须符合Vector的规范,否则DiVa加载时会报错。
DTC的触发条件。CDD里可以定义DTC的触发条件(比如某个信号超过阈值持续一定时间),DiVa会根据这些条件生成故障注入测试用例。但如果触发条件定义得太复杂,DiVa可能无法自动生成用例,需要手动补充。
提示:CDD制作完成后,建议先用CANoe的Diagnostic Console手动验证几个关键服务,确认CDD描述和ECU实际行为一致,再导入DiVa生成用例。这样可以避免批量执行时大面积失败,排查起来也更轻松。
3. DiVa工程配置:从CDD到测试用例的映射
3.1 DiVa在CANoe中的集成方式
DiVa不是一个独立的可执行程序,它是以CANoe选件的形式集成的。你需要在CANoe的配置界面里激活DiVa功能,然后新建一个DiVa Test Unit。具体路径是:在CANoe的Simulation Setup里添加一个Test Node,然后在Test Node的配置里选择DiVa作为测试执行引擎。
这里有个细节:DiVa Test Unit需要绑定一个诊断描述文件。你可以在Test Unit的属性里指定CDD文件的路径,DiVa会自动解析CDD里的诊断对象。如果CDD有更新,DiVa会提示你重新加载。
另一个关键配置是通信通道。DiVa需要通过CANoe的诊断通道发送请求,所以你要确保CANoe的Diagnostic Channel已经正确配置了CAN ID、波特率、寻址方式等参数。如果是DoIP(Diagnostics over IP),还需要配置IP地址、端口号、逻辑地址等。
3.2 测试用例的自动生成策略
DiVa生成测试用例的逻辑是基于CDD里的诊断对象和预定义的测试模板。它会为每个诊断服务生成一组标准用例,包括:
- 正向测试:在正确的会话和安全等级下发送请求,验证正响应格式和内容。
- 负向测试:在错误的会话或安全等级下发送请求,验证返回正确的否定响应码(NRC)。
- 边界测试:对DID的写入值进行边界值测试,比如最小值、最大值、超出范围的值。
- 序列测试:验证多个服务之间的依赖关系,比如先解锁安全等级再写DID。
- 超时测试:验证ECU在P2超时后的响应行为。
这些用例的生成规则可以在DiVa的配置界面里调整。比如你可以选择是否生成负向测试、是否启用边界值测试、是否包含DTC相关的测试。我的经验是:首次跑通流程时,先只生成正向测试,确认基本通信没问题,再逐步开启其他类型的测试。
3.3 测试用例的筛选与定制
DiVa自动生成的用例数量可能非常庞大。一个中等复杂度的ECU,CDD里如果有50个DID、20个DTC、10个例程,生成的用例可能上千条。全跑一遍耗时很长,所以需要筛选。
筛选策略可以从几个维度考虑:
- 按服务类型筛选:优先跑0x10、0x27、0x22、0x2E这些核心服务,0x19和0x14可以后续再跑。
- 按会话筛选:先跑默认会话下的用例,再跑扩展会话和编程会话。
- 按优先级筛选:DiVa允许给用例打标签,你可以根据项目需求标记高优先级用例。
如果自动生成的用例不满足需求,DiVa也支持手动创建测试用例。手动用例可以用CAPL编写,也可以基于DiVa的Test Case Editor用图形化方式配置。手动用例的好处是可以针对特定场景做定制,比如模拟特定的故障注入序列。
3.4 测试环境的准备与检查清单
在正式执行DiVa测试之前,建议按下面的清单过一遍:
| 检查项 | 说明 | 常见问题 |
|---|---|---|
| CANoe通道配置 | 确认CAN通道或DoIP通道已正确配置 | 通道未激活、波特率不匹配 |
| 诊断描述文件 | CDD已加载且无解析错误 | CDD版本与ECU不一致 |
| ECU供电与连接 | ECU已上电,CAN线或以太网连接正常 | 线束接触不良、终端电阻缺失 |
| 安全算法 | 安全访问DLL已正确加载 | DLL路径错误、接口不匹配 |
| 测试用例集 | 已根据需求筛选用例 | 用例过多导致执行时间过长 |
| 报告路径 | 已配置文件系统输出目录 | 路径不存在或权限不足 |
这张表里的每一项我都踩过坑。特别是安全算法DLL的问题,DiVa在加载失败时给出的错误信息往往很模糊,需要看CANoe的Write窗口才能找到具体原因。
4. 实操过程:从工程搭建到报告输出
4.1 新建DiVa工程并导入CDD
打开CANoe,新建一个Configuration。在Simulation Setup里右键添加一个Test Node,然后在Test Node的配置里选择DiVa。接下来在DiVa的Test Unit配置界面里,点击“Add”按钮导入CDD文件。导入过程中DiVa会解析CDD,如果CDD有语法错误或引用缺失,会在这里报出来。
导入成功后,你可以在DiVa的Test Case Browser里看到自动生成的测试用例树。用例按诊断服务分类,每个服务下面有正向、负向、边界等子类。建议先展开几个核心服务,检查一下用例的请求参数是否符合预期。
4.2 配置诊断通道与通信参数
在CANoe的Diagnostic Configuration里,确认诊断通道的CAN ID和寻址方式。如果是物理寻址,请求ID通常是0x7xx,响应ID是0x7xx+8。功能寻址的请求ID通常是0x7DF。这些参数必须和CDD里的定义一致,否则DiVa发送的请求ECU收不到。
如果是DoIP,需要在Diagnostic Configuration里选择DoIP协议,然后配置ECU的IP地址、端口号(通常是13400)、逻辑地址(源地址和目标地址)。DoIP的好处是传输速度快,适合刷写场景,但配置比CAN复杂,容易在逻辑地址上出错。
P2和P2超时时间也要在CDD里定义好。P2是ECU收到请求后开始响应的时间,P2是ECU发送否定响应0x78后继续等待的时间。DiVa会根据这些超时时间判断ECU是否响应超时。如果超时时间设得太短,ECU还没来得及响应就被判失败;设得太长,测试执行效率低。
4.3 执行测试与实时监控
配置完成后,点击DiVa的“Run”按钮开始执行测试。CANoe会依次发送诊断请求,并在Trace窗口里显示请求和响应的原始报文。DiVa的Test Report窗口会实时更新每条用例的执行状态:绿色是通过,红色是失败,黄色是警告。
执行过程中可以随时暂停,查看当前用例的详细信息。如果某条用例失败,可以双击打开,查看请求报文、响应报文、期望值和实际值的对比。这个对比信息对于排查问题非常有用。
我通常会在执行时同时打开Trace窗口和Diagnostic Console。Trace窗口用来看原始报文,Diagnostic Console用来手动发送诊断请求做对比验证。如果DiVa报某条用例失败,我会在Diagnostic Console里手动发一遍同样的请求,看看ECU的实际响应是什么,从而判断是CDD描述错了还是ECU实现有问题。
4.4 测试报告的生成与解读
测试执行完成后,DiVa会生成一份测试报告。报告格式可以是HTML、XML或PDF,我一般用HTML,因为可以在浏览器里直接查看,而且支持展开/折叠用例详情。
报告里每条用例会包含以下信息:
- 用例名称和描述
- 请求报文(十六进制)
- 期望响应
- 实际响应
- 判定结果(Pass/Fail/Inconclusive)
- 失败原因(如果有)
解读报告时,重点关注Fail和Inconclusive的用例。Fail通常意味着ECU的实际行为与CDD描述不符,需要进一步排查是CDD的问题还是ECU的问题。Inconclusive通常是因为测试条件不满足(比如ECU未进入正确的会话),需要检查测试环境。
报告里还有一个汇总统计,显示通过率、失败数、警告数。这个统计可以用来评估ECU的诊断符合性。如果通过率低于预期,建议先检查CDD的准确性,再检查ECU的实现。
4.5 持续集成中的DiVa自动化
如果项目需要频繁回归,可以把DiVa集成到持续集成流程里。CANoe支持命令行启动,DiVa测试可以通过COM接口或CANoe的Test Automation功能自动触发。具体做法是:写一个批处理脚本,调用CANoe.exe并传入配置文件路径,CANoe启动后自动加载DiVa工程并执行测试,最后把报告输出到指定目录。
这个流程可以进一步和Jenkins等CI工具集成,实现每次代码提交后自动跑诊断回归。不过要注意,DiVa测试需要真实的ECU或仿真节点,所以CI环境里要么有硬件在环(HIL)台架,要么用CANoe的仿真节点模拟ECU响应。
5. 常见问题与排查技巧实录
5.1 诊断请求无响应或超时
这是最常见的问题,可能的原因和排查思路如下:
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 所有请求都无响应 | CAN通道未激活或线束未连接 | 检查CANoe通道状态和物理连接 |
| 部分请求无响应 | CAN ID配置错误 | 对比CDD和CANoe的Diagnostic Configuration |
| 响应超时 | P2时间设置过短 | 增大CDD里的P2时间,重新生成用例 |
| DoIP请求无响应 | IP地址或逻辑地址错误 | 用ping命令测试ECU的IP连通性 |
| 功能寻址无响应 | ECU不支持功能寻址 | 检查CDD里的寻址方式定义 |
我遇到过一次所有请求都无响应的情况,排查了半天发现是CANoe的通道配置里波特率设成了500k,而ECU实际是250k。这种低级错误在紧张的项目节点上特别容易犯,建议每次搭建环境后先用Diagnostic Console手动发一条0x10 0x01确认通信正常。
5.2 否定响应码不符合预期
DiVa生成的负向测试用例会期望ECU返回特定的NRC。如果实际返回的NRC和期望不一致,用例就会失败。常见的NRC不匹配场景:
- 期望0x7F但收到0x12:ECU不支持该服务,但CDD里定义了这个服务。需要确认ECU是否真的实现了该服务。
- 期望0x33但收到0x22:安全访问未解锁时的NRC应该是0x33(安全访问拒绝),但ECU返回了0x22(条件不满足)。这通常是ECU的状态机实现和CDD描述不一致。
- 期望0x31但收到0x13:请求长度或格式错误时的NRC应该是0x13,但ECU返回了0x31(请求超出范围)。需要检查请求参数的长度定义。
这类问题的根源往往是CDD描述和ECU实现之间的偏差。解决方法是:先用Diagnostic Console手动发送请求,确认ECU的实际响应,然后修改CDD里的期望值,重新生成用例。
5.3 安全访问解锁失败
安全访问是诊断测试里最容易出问题的环节。DiVa在执行0x27服务测试时,会先请求种子,然后用配置的算法计算密钥,再发送密钥。如果解锁失败,可能的原因包括:
- 种子和密钥算法不匹配:CDD里配置的算法和ECU实际使用的算法不一致。需要和ECU开发人员确认算法细节。
- 安全等级定义错误:CDD里定义的安全等级和ECU的实际等级不对应。比如CDD里Level 1对应0x01子功能,但ECU实际用0x11。
- 会话状态不对:安全访问通常需要在扩展会话下进行,如果当前是默认会话,ECU会返回0x7F。
- DLL加载失败:安全算法的DLL没有正确加载,DiVa无法计算密钥。检查CANoe的Write窗口是否有DLL加载错误。
我个人的经验是:安全访问的算法最好在项目早期就和ECU开发人员对齐,并且用单元测试验证DLL的正确性。不要等到DiVa测试时才去调试算法,那样排查起来非常痛苦。
5.4 DTC相关测试的注意事项
0x19和0x14服务的测试相对复杂,因为涉及到故障码的触发和清除。DiVa生成的DTC测试用例通常包括:
- 读取DTC数量(0x19 0x01)
- 读取DTC快照数据(0x19 0x04)
- 读取DTC扩展数据(0x19 0x06)
- 清除DTC(0x14)
执行这些用例时,需要确保ECU处于正确的状态。比如读取DTC快照数据前,需要先触发一个故障,否则快照数据为空。DiVa支持通过故障注入的方式触发DTC,但需要CDD里定义了故障触发条件。
清除DTC后,建议等待几秒钟再读取DTC,因为ECU内部清除故障码可能需要时间。如果立即读取,可能还会读到旧的故障码,导致用例失败。
5.5 测试执行效率优化
DiVa测试的执行时间主要取决于用例数量和每条用例的响应时间。如果用例上千条,全跑一遍可能需要几个小时。优化效率的几个方法:
- 并行执行:如果CANoe支持多通道,可以把用例分配到不同通道并行执行。但要注意ECU是否支持并发诊断请求。
- 用例筛选:只跑核心用例,非核心用例定期跑一次即可。
- 缩短超时时间:在保证ECU能正常响应的前提下,尽量缩短P2和P2*时间。
- 使用DoIP:DoIP的传输速度比CAN快很多,适合刷写和大数据量读取场景。
注意:缩短超时时间时要谨慎,特别是在ECU负载较高的情况下,响应时间可能会变长。建议先测量ECU的实际响应时间,再设置合理的超时值。
6. 从实战中沉淀下来的经验
CDD文件的质量决定了DiVa测试的天花板。我现在的习惯是:拿到CDD后先花半天时间用CANdelaStudio过一遍,重点检查会话状态机、DID权限、DTC触发条件这三块。这半天的投入能省掉后面几天的排查时间。
DiVa的测试用例不是越多越好。首次跑通流程时,建议只启用正向测试,确认基本通信和会话切换没问题。然后再逐步开启负向测试和边界测试。一次性全开的话,失败用例太多,根本看不过来。
安全访问的调试要趁早。我一般会在CDD制作阶段就用CANoe的Diagnostic Console手动验证安全访问流程,确认种子和密钥算法正确后,再导入DiVa。这样能避免DiVa测试时因为算法问题导致大量用例失败。
测试报告要存档。每次回归的DiVa报告都保存下来,对比不同版本的通过率变化。如果某个版本的通过率突然下降,说明ECU的诊断实现可能引入了回归问题。这种趋势分析比单次测试结果更有价值。
最后分享一个实用技巧:DiVa的测试用例支持导出为CAPL脚本。如果你需要对某条用例做定制修改,可以导出后用CAPL编辑器修改,然后再导入DiVa。这样既保留了DiVa的自动化框架,又能灵活应对特殊场景。