1. 方案背景与整体设计思路
1.1 这套组合到底解决了什么问题
做汽车电子控制器测试的朋友,对ECUTEST应该不陌生。它的测试用例结构化、报告可追溯,跑回归测试非常顺手。但ECUTEST本质上更偏“测试执行管理”,面对复杂的总线信号场景时,就显得有些笨重:你想在某个关键时刻往CAN总线塞一个车速信号,或者想捕获某个报文后立刻改变测试节奏,光靠ECUTEST本身很难灵活实现。
这时候就需要一个“总线模拟+信号监控”的搭档。TSMaster作为一款总线工具,在CAN/CAN FD/LIN/Ethernet等信号仿真与监控方面很灵活,而且提供了API接口,可以用脚本外部调用。把两者结合起来,Python脚本作为“总指挥”:一边通过TSMasterAPI控制CAN信号,一边通过ECUTEST的自动化接口驱动测试用例执行。这才是标题里“高阶玩法”的核心价值——不是简单把两个工具凑在一起,而是形成一套可编程、可扩展、可复用的自动化测试闭环。
这种架构特别适合三类团队:一是测试环境里已经买了ECUTEST但缺少总线仿真工具的团队;二是希望把原来人工操作TSMaster和ECUTEST的流程改造成全自动回归的团队;三是正在建设CI持续集成,想让ECU测试也能一键触发、自动收集报告的团队。如果你属于其中任何一种,这套方案都值得认真研究。
1.2 为什么选TSMasterAPI而不是CANoe/CAPL
很多人第一反应是用CANoe搭配ECUTEST,毕竟都是Vector系,集成度好。但这个方案有几个现实问题:CANoe授权成本高,项目组不一定有预算;CAPL脚本学习曲线陡峭,写起来调试也费劲;另外CANoe的自动化维度更多绑定在Vector生态里,想接第三方工具链反而麻烦。
TSMasterAPI的优势在于“开放”和“轻量”。一方面,TSMaster本身提供了完善的API,支持通过Python、C#等语言外部调用,开发门槛低;另一方面,TSMaster的授权成本相对友好,部署灵活,很适合作为测试台架上常驻的总线中间件。再加上Python在测试领域已经成了“事实标准语言”,用Python做总控,后续无论是接Jenkins、做数据分析还是生成可视化报告,生态都非常成熟。
当然,也不是说TSMaster能完全替代CANoe,比如硬件兼容性方面,TSMaster通常配合自家硬件或部分第三方案件使用,如果你是纯粹CANoe独家硬件环境,那还得老实评估。但对于大多数CAN信号级交互的场景,TSMasterAPI这套方案完全够用,而且性价比高得多。
1.3 整体架构和数据流向
先把整套架构在脑子里画清楚,后面写代码才不会乱。典型架构分三层:
- 控制层:Python脚本,负责整体流程编排、时序控制、结果判断。
- 工具层:TSMaster负责CAN通道建立、报文发送、信号解析;ECUTEST负责加载测试工程、执行用例、产出测试报告。
- 被测对象层:ECU或ECU台架,通过CAN总线与TSMaster连接。
数据流向大致是:Python脚本通过TSMasterAPI发送初始化信号(比如电源模式、点火状态)给ECU;ECU上电后回发状态报文;Python读取信号后判断条件满足,再通过ECUTEST的接口启动对应测试用例;测试执行过程中,Python持续监控总线信号,根据信号变化决定是否继续、暂停或终止;测试结束后,Python从ECUTEST拉取执行结果,与总线日志一起汇总。
这个分层的好处是职责清晰:TSMaster只干“总线的活”,ECUTEST只干“测试用例的活”,Python只干“编排的活”。哪一层出问题,定位起来非常快。我在实际项目里维护这套体系已经跑过几万条用例,最深的感受就是:信号和用例解耦之后,新增一个测试场景时,往往只需要加一段Python流程,不用去动ECUTEST里的框架代码。
2. 环境准备与工具链搭建
2.1 安装TSMaster并开启API支持
TSMaster安装不算复杂,官方下载安装包后按向导安装即可。需要注意两点:一是安装时尽量勾选完整组件,尤其是API文档和示例工程,后面写代码翻文档很有用;二是安装完成后确认软件能正常启动,推荐先手动创建一个CAN工程,把通道、波特率、DBC文件这些基础配置调通,再进入API开发阶段。
TSMaster的API支持方式根据版本不同有所差异,有的是COM接口形式,有的是动态库加Python绑定。无论哪种,原理都一样:先启动TSMaster应用(或者API进程),然后通过代码连接并操作。如果是COM方式,在Windows上通常会注册好组件,可以直接用win32com或者comtypes去调用;如果是DLL方式,则需要自己加载动态库并声明函数原型。
我建议你第一步不要直接写代码,而是先打开TSMaster安装目录下的Samples或API Example文件夹,找到Python示例,跑通一个“连接TSMaster并读取版本号”的最小Demo。这一步能帮你确认API环境是否配好,也避免了后面一上来就踩连接坑。
2.2 安装ECUTEST并准备好测试工程
ECUTEST安装过程没什么特别,关键在安装完成后要确认自动化接口可访问。ECUTEST对外提供COM自动化接口(通常叫Automation Interface),不同版本暴露的方式可能不同,有的需要安装时勾选“Automation API”组件,有的需要在系统中注册DLL。你可以在安装目录的文档里搜索“Automation Interface”或者“COM Client”,里面会说明如何从外部程序调用。
测试工程准备这一步更容易被忽略,但恰恰很重要。我遇到过不少新手,脚本写好了,运行ECUTEST时报“无法加载工程”,排查半天发现是测试工程路径里有中文或者特殊字符,导致COM接口解析失败。所以建议:测试工程放在纯英文路径下,工程名也尽量用字母和下划线;在ECUTEST里先手动把工程打开一遍,确认能正常跑通一条用例,再交给Python控制。
另外,要提前梳理清楚测试工程里用例的层级结构:哪个是Test Configuration,哪个是Test Group,哪个是具体TestCase。因为脚本控制时要通过这些名字去定位要执行的测试对象,名字写错一个字符都会出问题。
2.3 Python环境搭建(Windows场景)
Python版本建议用3.8到3.11之间,太新的版本有时对COM相关库兼容性不稳定。安装时勾选“Add Python to PATH”,避免后面命令行找不到。
需要装的库不多,核心就两个:
pip install pywin32 pip install pandaspywin32用来调用Windows COM组件,pandas用来处理测试结果和日志数据。如果你还需要做图表,可以加装openpyxl或者matplotlib,但前期不用,保持环境干净。
装好后,在Python命令行里验证一下COM组件能不能正常创建:
import win32com.client as win32 # 验证ECUTEST COM接口是否能创建,具体ProgID以版本为准 app = win32.Dispatch("ECUTest.Application") print(app)这一步能通过,说明ECUTEST的自动化接口暴露成功。TSMaster的验证方式类似,根据实际API形式来,如果是DLL方式,就直接import对应Python模块试试。环境准备这块不难,但一定要逐项确认都通了再往下走,否则后面全嵌套在一起,排查起来非常头疼。
提示:我在现场调试时踩过最多的坑就是“32位/64位不匹配”。Python、TSMaster API组件、ECUTEST COM组件如果位数不一致,会出现Dispatch失败或者调用无响应。建议统一使用64位。
3. 核心细节:Python调用TSMasterAPI的姿势
3.1 连接TSMaster并初始化总线
TSMasterAPI的调用逻辑和手动操作软件是等价的:先建立连接,再打开/创建一个工程,然后配置总线通道和数据库文件。
举个典型的连接片段(接口名称以TSMaster安装文档为准,我这里按常见API习惯写):
import win32com.client as win32 # 创建TSMaster COM对象(实际ProgID请查阅TSMaster API手册) tmaster = win32.Dispatch("TSMaster.Application") # 初始化API环境 tmaster.Initialize() # 打开现有工程,工程里已配置好CAN通道和DBC文件 tmaster.OpenProject(r"D:\TestProjects\BCM_Test.tse") # 启动总线通信(等效于点击软件的"在线"按钮) tmaster.Start()这里有几个关键点要强调。第一,OpenProject的参数最好是工程文件的绝对路径,因为COM调用和相对路径的组合经常出幺蛾子。第二,Start启动总线通信后,最好先停顿一两秒,等底层硬件初始化完成,再发报文,否则第一帧数据可能发不出去。第三,如果TSMaster不是COM方式而是DLL方式,思路完全一样,只是换一套加载动态库的写法,核心流程仍然是“连接→开工程→启动”。
关于TSMasterAPI的详细接口清单,强烈建议直接看安装目录里的帮助文档。有些接口名字很相似,比如“SendRequest”和“SendMessage”,实际用途完全不同,写之前先查文档能省很多返工时间。
3.2 发送CAN报文与信号值写入
连接好之后,下一步就是往CAN总线上发报文。这里重点讲信号级操作,因为我们最终关注的是某个物理信号,比如车速、温度、档位,而不是原始字节。
先看一个直接发报文的例子:
import time def send_speed_message(speed_value): # 假设车速报文ID为0x123,波特率在工程里已配好 msg = tmaster.CreateCANMessage() msg.ID = 0x123 msg.DLC = 8 # 手动填数据字节(这里演示简单封装:前两个字节表示车速,精度0.01) msg.Data[0] = speed_value & 0xFF msg.Data[1] = (speed_value >> 8) & 0xFF tmaster.SendCANMessage(msg) send_speed_message(3000) # 相当于30.00 km/h这种原生字节拼接方式适合简单报文,但真实工程里报文都定义了DBC,信号分布在字节的不同位、不同字节序,手动拼接极其容易出错。更推荐的方式是用DBC数据库解析信号,然后直接按信号名赋值:
def set_signal_by_name(msg_id, signal_name, value): msg = tmaster.CreateCANMessage() msg.ID = msg_id # 加载DBC后,可以直接引用信号 tmaster.SetSignal(msg, signal_name, value) tmaster.SendCANMessage(msg) set_signal_by_name(0x123, "VehicleSpeed", 30.0)思路虽然简单,但实际API可能叫SetSignalValue或者SetSignal,取决于版本。不管叫什么,这个能力非常重要:你不再关心信号在哪个字节、要不要移位,DBC帮你算好了。这也是为什么在TSMaster里配置好DBC文件比写一堆位运算要可靠得多。
发送模式上,有“单次发送”和“周期发送”两种。日常测试里,周期发送更接近真实总线行为,比如车速报文通常是10ms或100ms周期循环发送。TSMasterAPI里一般有周期发送的设置方法,可以指定周期时间。如果API不支持周期性发送,也可以用Python线程自己定时发送,但要注意定时精度,Windows下线程定时不够稳定,能交给工具配置就交给工具配置。
3.3 读取接收到的CAN信号
接收方向是CAN信号交互的另一个重点。很多时候我们需要读取ECU发来的反馈报文,判断当前是否达到预期状态。
实现方式通常是两种:主动读取和回调通知。主动读取最简单:先调用接收接口从缓冲区里取最新报文,再解析信号值。比如:
def read_light_status(): # 读取ID为0x456的报文,返回灯光状态信号 msg = tmaster.ReadCANMessage(0x456) if msg is None: return -1 status = tmaster.GetSignal(msg, "LightStatus") return status主动读取适合轮询场景,比如每100ms检查一次ECU状态。但轮询周期不好确定:太快了CPU开销大,太慢了可能错过关键信号。如果TSMasterAPI支持回调或事件订阅,优先用回调,信号到来时自动通知Python,实时性和准确性都更好。
这里给一个非常重要的经验:信号读取和测试流程控制在Python里最好分开。不要在读取信号的回调函数里直接做复杂的流程判断,而是把信号值缓存到一个队列,主流程从队列里消费。否则会出现回调执行时间过长导致后续报文丢失的问题,排查起来非常隐蔽。
我用一个简单例子说明信号缓存的思路:
import queue signal_queue = queue.Queue() def on_message_received(msg): # 假设这是TSMasterAPI的回调入口 if msg.ID == 0x456: status = tmaster.GetSignal(msg, "LightStatus") signal_queue.put(status) # 主流程 while True: try: status = signal_queue.get(timeout=2) if status == 1: trigger_testcase() break except queue.Empty: print("等待反馈信号超时")这段代码的核心就是“回调只负责入队,主流程负责处理”,既保证了实时性,又让流程逻辑清晰可读。
4. 用Python驱动ECUTEST跑测试
4.1 ECUTEST自动化接口初识
ECUTEST的自动化接口原理并不神秘:它对外暴露COM对象,外部程序通过调度接口来加载工程、选择测试用例、触发执行、查询状态。这和我们前面操作TSMasterAPI完全是一个思路。
常用的对象层级大致是:
- Application:代表整个ECUTEST实例,负责启动、退出。
- Project / TestConfiguration:代表加载进来的测试工程。
- TestManager:负责具体执行用例、暂停、停止。
- Result / Report:负责获取执行结果。
不同的ECUTEST版本,类名和方法名会有些差异,但整体结构比较固定。所以第一件事永远是:打开ECUTEST安装目录下的Automation帮助文档,先把它提供的对象模型图看一遍。以前我为了找“如何获取某个测试用例的执行结果”,翻了不少文档,最后发现不同版本里方法名从GetResult变成了GetTestResultInfo,直接照抄旧版本的代码就跑不通。
4.2 启动和停止一个测试工程
这里给一个简化的调用示例,展示“连接ECUTEST→打开工程→执行所有用例→等待结束→取结果”的完整骨架(同样,具体接口名以你的版本为准):
import win32com.client as win32 # 创建ECUTEST应用对象 ecu_app = win32.Dispatch("ECUTest.Application") ecu_app.Visible = False # 后台运行,不弹界面 # 打开测试工程 ecu_app.OpenProject(r"D:\TestProjects\BCM_Test.ets") # 拿到工程对象并执行 test_project = ecu_app.GetActiveProject() test_project.ExecuteAllTests() # 等待执行结束(轮询状态) while test_project.IsRunning(): time.sleep(0.5) # 获取最终结果 report_path = test_project.GetReportPath() print(f"测试报告已生成:{report_path}")这个小例子已经能解决“一键跑完整个工程”的需求。但实际项目中往往更复杂:有时候不是跑全部用例,而是按标签动态选择某几个用例;有时候要在测试执行过程中根据总线信号决定是否跳过某个测试步骤。
4.3 与CAN信号交互的流程控制
真正把TSMasterAPI和ECUTEST结合起来时,核心就是“信号判断控制用例执行”。这有两种主流模式。
模式一:信号就绪后再启动测试。先通过TSMasterAPI把ECU激活到指定状态(比如点火信号置ON、档位信号置D),然后启动ECUTEST执行用例。因为用例内部假设了前置条件已经满足。
模式二:测试执行中动态响应信号。比如ECUTEST正在执行一个交互式用例,等待操作者确认某个现象;此时Python通过TSMasterAPI监控CAN总线,一旦发现ECU回复了成功帧,就调用ECUTEST接口让用例继续执行,或者直接标记该步骤通过。
不管哪种模式,代码组织上都可以抽象成模板:
def run_testcase_when_signal_ready(signal_name, target_value, testcase_name): # 1. 先监控总线信号,直到满足条件 while True: value = read_signal(signal_name) if value == target_value: break time.sleep(0.1) # 2. 信号已就绪,启动ECUTEST用例 test_project.ExecuteTestCase(testcase_name) # 3. 等待用例执行结束,读取结果 while test_project.IsTestCaseRunning(testcase_name): time.sleep(0.5) return test_project.GetTestCaseResult(testcase_name)这种模板看起来简单,但已经能在很多台架自动化项目中落地了。剩下的是处理好异常分支:如果循环等信号超时,要主动报错并终止,否则脚本会一直挂在那里。
5. 实操案例:一个CAN信号交互的完整示例
5.1 案例场景描述
我拿一个典型的车身控制器(BCM)测试案例来演示完整流程。场景是这样的:BCM上电后,需要外部网关周期发送电源模式信号(0x100报文,信号PowerMode),当电源模式切换为“正常运行”时,BCM会上电并开始响应灯光控制指令;然后我们发送“左转灯开关”信号(0x123报文,信号TurnLightCmd),正常情况下BCM会回发一条状态报文(0x456报文,信号TurnLightSts),且状态值在1秒内变为“开启”。
传统测试做法是:人先在TSMaster里手动发几条报文,再跑到ECUTEST里点执行用例,观察结果,再手动记录。整个流程繁琐且容易遗漏时间节点。我们的自动化目标很明确:
- Python自动发送0x100报文,设置PowerMode=2(正常运行);
- 等待BCM返回Ready报文(简化处理:等待100ms);
- 启动ECUTEST中的测试用例“验证左转灯开启功能”;
- 用例执行过程中,Python不断读取0x456报文的TurnLightSts信号;
- 当TurnLightSts变为1时,记录时间戳,并调用ECUTEST接口给该用例注入“通过”结论;
- 如果超过1秒未变化,则报告失败。
需要说明:真实BCM时序会更复杂,这里聚焦在“CAN信号交互”这个核心逻辑上。
5.2 完整Python脚本示范
下面的代码我按实际工程里的风格来写,关键调用处保留注释。你需要根据自己的TSMaster和ECUTEST版本微调接口名,但整体框架是通用的。
import win32com.client as win32 import time import logging import queue logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s") # ---------- 工具对象初始化 ---------- tmaster = win32.Dispatch("TSMaster.Application") tmaster.Initialize() tmaster.OpenProject(r"D:\TestProjects\BCM_HIL.tse") tmaster.Start() time.sleep(1) ecu_app = win32.Dispatch("ECUTest.Application") ecu_app.Visible = False ecu_app.OpenProject(r"D:\TestProjects\BCM_Test.ets") test_project = ecu_app.GetActiveProject() logging.info("TSMaster与ECUTEST连接成功") # ---------- 工具函数 ---------- def set_engine_signal(power_mode): """通过0x100报文设置电源模式""" msg = tmaster.CreateCANMessage() msg.ID = 0x100 tmaster.SetSignal(msg, "PowerMode", power_mode) tmaster.SendCANMessage(msg) def send_turnlight_cmd(value): """发送左转灯开/关指令""" msg = tmaster.CreateCANMessage() msg.ID = 0x123 tmaster.SetSignal(msg, "TurnLightCmd", value) tmaster.SendCANMessage(msg) def read_light_status(): """读取BCM回发的左转灯状态信号""" msg = tmaster.ReadCANMessage(0x456) if msg is None: return -1 return tmaster.GetSignal(msg, "TurnLightSts") # ---------- 信号队列回调(如果API支持) ---------- signal_queue = queue.Queue() def on_msg(msg): if msg.ID == 0x456: status = tmaster.GetSignal(msg, "TurnLightSts") signal_queue.put(status) # tmaster.SetMessageCallback(on_msg) # 实际API可能叫RegisterCallback,按文档调整 # ---------- 主流程 ---------- def main(): logging.info("步骤1:设置电源模式为正常") set_engine_signal(2) time.sleep(0.2) logging.info("步骤2:启动ECUTEST相关测试用例") test_project.ExecuteTestCase("验证左转灯开启功能") logging.info("步骤3:等待BCM回发灯光状态信号") start_time = time.time() status = -1 while time.time() - start_time < 1.0: # 优先从队列取,取不到再主动读 try: status = signal_queue.get(timeout=0.1) except queue.Empty: status = read_light_status() if status == 1: logging.info("灯光状态在%.1fms内变为开启", (time.time() - start_time) * 1000) break time.sleep(0.05) else: logging.error("等待超时,灯光状态未变,当前status=%s", status) # 步骤4:根据结果设置ECUTEST测试结论 if status == 1: test_project.SetCurrentTestResult("PASS") logging.info("测试通过") else: test_project.SetCurrentTestResult("FAIL") logging.info("测试失败") # 步骤5:等待用例结束,输出报告路径 while test_project.IsRunning(): time.sleep(0.2) logging.info("最终报告:%s", test_project.GetReportPath()) # 清理 tmaster.Stop() ecu_app.Quit() if __name__ == "__main__": main()5.3 案例执行过程与结果解读
上面脚本跑起来后,日志大概是这样的:
2025-01-10 10:00:01 [INFO] TSMaster与ECUTEST连接成功 2025-01-10 10:00:01 [INFO] 步骤1:设置电源模式为正常 2025-01-10 10:00:02 [INFO] 步骤2:启动ECUTEST相关测试用例 2025-01-10 10:00:02 [INFO] 步骤3:等待BCM回发灯光状态信号 2025-01-10 10:00:02 [INFO] 灯光状态在120.5ms内变为开启 2025-01-10 10:00:03 [INFO] 测试通过 2025-01-10 10:00:03 [INFO] 最终报告:D:\TestProjects\BCM_Test\Report\...如果你看到灯光状态在120ms左右变化,说明BCM响应正常,测试通过。如果超时,多半是以下原因:
- 电源模式信号发送后,BCM还在启动过程中,需要更长延时;
- 0x456报文的DBC信号定义有误,
GetSignal返回-1; - 发送0x123报文后,报文周期太短或丢失,BCM没收到指令。
我在调试这个案例时,真正花时间的不是代码本身,而是确认信号能不能在正确的时间“摸到”。后来我在代码里加了信号值实时打印,把每一步读到的信号都记录下来,问题一下变清晰了。建议你也这么干,不要只关注最终PASS/FAIL。
6. 常见问题与排查技巧实录
6.1 连接与初始化问题速查表
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| Dispatch创建TSMaster对象失败 | COM组件未注册、Python位数不一致 | 确认TSMaster安装完整,检查Python解释器位数 |
| OpenProject报路径异常 | 工程路径含中文/特殊字符 | 路径改为纯英文,且用绝对路径 |
| ECUTEST启动后没有窗口 | Visible设置问题或实例冲突 | 检查是否已有ECUTEST进程,先杀掉再试 |
| Start总线通信后发不出去报文 | 硬件未识别、通道配置错误 | 在TSMaster界面手动启动一次,确认硬件通道 |
| 读取报文一直为None | 报文ID或通道错误,总线无数据 | 先用TSMaster软件的报文监视器确认信号是否到达 |
遇到连接问题,我自己的习惯是:先手动把TSMaster和ECUTEST都操作一遍,确保链路本身正常,再跑脚本。脚本失败时,加个异常打印,把报错行堆栈贴出来,基本能定位80%的问题。
6.2 信号收发与解析的坑
CAN信号交互看起来只是“发报文、读报文”,但实际里坑不少。第一个坑是大小端和位序。DBC文件里Motorola格式和Intel格式的信号,底层位排列完全不同。如果直接用API读信号返回异常值,先检查DBC里信号定义是不是符合ECU软件设计文档。
第二个坑是信号初始值。有些报文在ECU没有输出前,线上保持隐性电平,API读出来可能是0,也可能是上一次的缓存值。这会导致状态判断错误。解决办法是在测试开始前先清空接收缓冲区,或者等待一段时间再读。
第三个坑是时间戳。如果要做时序判断(比如“1秒内信号到位”),建议先把TSMaster的时间戳读出来,而不是直接用Python的time.time()。因为两套工具的时间基准可能不同,跨工具比较会有毫秒级偏差,做严格时序测试时容易误判。
6.3 流程控制与长时间运行稳定性
跑一趟自动化可能只有几分钟,但回归测试往往要跑几小时甚至过夜。这时候最容易遇到两个问题。
一是ECUTEST或TSMaster长时间运行后出现内存增长或响应变慢。我的经验是:每执行完一批用例,定期释放COM对象(在Python里可以显式置None并调用gc.collect());如果ECUTEST界面长期不可见,偶发放置后台无响应,可以在脚本里加“心跳检测”,定期检查应用状态,一旦发现异常就强制重启并恢复现场。
二是网络和外部依赖不稳定。如果你的脚本里还有数据库、诊断仪等其他依赖,建议在关键步骤加超时和重试机制。不要用裸的无限等待,任何等待都要设置上限。
提示:长时间挂机测试,一定要把日志做好,建议同时输出到文件和控制台,文件名带上时间戳。不然第二天早上看到全红,可能连问题发生的时间点都找不到。
6.4 一些小众但实用的避坑技巧
- 不要依赖全局变量管理COM对象:TSMaster和ECUTEST实例尽量在函数内创建和释放,避免循环调用时对象状态混乱。
- 调试阶段把两个工具的界面都显示出来:虽然Visible=False更“自动化”,但初期调试时还是让软件界面可见,能看到信号收发和用例执行过程,事半功倍。
- CAN信号交互别用单次发送:对于某些ECU,单次报文容易丢,建议在需要时用周期发送(比如10ms周期发10帧),稳定后再停止。
- DBC文件改完,要重新加载:TSMasterAPI不会自动热更新DBC,手动改了DBC后,脚本里要重新打开工程或调用刷新接口。
按这套经验,我在实际项目里从零搭建到稳定运行,大概花了两天半时间,其中一半时间都花在调CAN信号上,真正写ECUTEST调用反而很快。所以如果你刚接触,耐心点多花点时间在信号层面,把发送和读取摸熟了,整个方案就成功一大半了。
这个内容后续还可以往两个方向扩展:一是把TSMasterAPI换成TSMaster的硬件在环仿真模式,结合ECUTEST做更复杂的HIL闭环;二是把整个Python脚本封装成服务,接到Jenkins或自研测试平台上,实现自动触发、自动分析、自动归档报告。到时候整套测试就不再依赖人工干预,回归效率会提升好几个量级。