
做车载座舱或者智能仪表测试的人大概率都经历过这样的场景版本提测后测试同学守在工位上对着中控屏、仪表屏、HUD反复操作一测就是一整天。也有人会写点自动化脚本可脚本跑完你依然得守在电脑前等结果再手动解析日志、截屏、贴报告逃不开“提测—回归—反馈—再回归”这个循环。我最近完成的一套方案把飞书机器人、AI Agent 和车载 HMI 自动化测试彻底打通了测试同学在飞书群里发一句“跑一遍中控蓝牙回归”机器人收到指令后自动调度测试环境、执行用例、调用 AI 分析失败原因最后把结论、截图和报告直接推回群里。整套平台跑下来单轮回归的人肉时间从几个小时压缩到十几分钟普通开发也能自己发起测试不再依赖专门的值守。这篇内容会把这套平台的架构拆解、关键实现和落地过程中踩过的坑一次说清楚。适合正在做车载 HMI 测试、座舱自动化测试或者想把 AI Agent 接进现有测试体系的人参考。1. 项目缘起这套平台到底要解决什么问题1.1 车载 HMI 测试的几个典型“卡点”车载 HMI 这几年边界一直在扩大。过去大家理解的 HMI 主要是中控大屏和数字仪表现在抬头显示、副驾娱乐屏、后排吸顶屏、电子后视镜显示都纳入了范围。多屏联动、跨屏流转、深浅色切换、语音和触控反馈叠加测试对象从单一屏幕变成了一个分布式显示系统。测试环节的麻烦主要来自三方面。第一是硬件耦合度高。HMI 的很多缺陷必须在真实硬件或至少等效仿真环境里才能暴露。比如仪表指针的刷新率、中控开机画面的启动时序、蓝牙连接后媒体信息的握手流程纯软件模拟根本压不出来。所以测试环境往往混着模拟器、域控制器、真车台架环境种类多切换费时。第二是回归频率高。座舱软件一个迭代版本能覆盖触控、显示、通信、语音等十几个模块提测之后常按天甚至按小时回归。每轮回归都靠人肉点屏视觉疲劳带来的漏测几乎是必然的。盯着屏幕看了四个小时一个短暂的显示跳变很可能就错过了。第三是结果链路长。一次完整测试后整理报告要花不少时间截图要标注、日志要抓取、失败用例要关联到具体代码模块。这个环节最烦但恰恰最依赖经验。从这些痛点倒推这套平台最需要的不是一个“更好的自动化测试框架”而是一个能把发起任务、执行测试、分析结果、回传信息全部串起来的调度中枢并且让人能通过最日常的入口去使用它。这是后面选择飞书机器人和 AI Agent 组合的根本原因。1.2 为什么是“飞书机器人 AI Agent”而不是传统 CI团队一开始有两条路一条是搭定时任务流水线把自动化测试塞进固定节奏里另一条是做一个 Web 平台给测试员一个网页界面去点按钮发起测试。这两条路都有实际问题。定时任务适合固定时段的回归但座舱测试经常是开发随口一句“我改了蓝牙协议栈麻烦跑一下相关用例”需要的是即时、定向、按需发起测试而不是等到半夜跑批。Web 平台能解决即时性但让测试、开发、产品都记住登录一个单独系统使用成本依然高实际用起来往往会沦为只有测试自己在用的工具。飞书机器人把入口放在了大家天天都在用的工作群里。任何人只要提及机器人并输入一句自然语言就能发起一次测试谁都不用学新系统。这是对话即入口的天然优势。AI Agent 解决的则是自动化之后的最后一公里。自动化框架能把用例跑起来但跑完之后的失败分析还得靠人看日志、看截图、判断是环境问题还是真缺陷。传统流水线在这里基本是断链的。引入 AI Agent 后它可以读取日志、比对截图、结合用例关联的代码路径给出分析建议把原本需要资深测试介入的环节交给模型预判人工只需要复核结论。所以这套组合的逻辑很直白飞书机器人降低使用门槛AI Agent 降低分析门槛。1.3 平台能力收敛成三个目标立项时没有把范围铺开只收敛成三类能力随时随地发起测试支持自然语言指令从飞书群发起可以指定测试子集、指定环境、指定执行深度。全流程自动化从任务调度、环境准备、用例执行、日志采集到报告生成尽量少人工干预。失败智能分析对失败用例AI 能结合日志和截图给出根因假设标记可疑模块供人工复核。这三类能力对应到架构上就是消息接入层、编排控制层和智能分析层后面详细拆。2. 系统架构设计与关键决策2.1 四层架构与一次完整链路平台的架构从高层看分四层消息接入层部署飞书机器人服务接收用户消息和按钮回调完成权限校验、消息解析和命令提取。编排控制层核心服务负责任务队列管理、状态机流转、用例筛选、执行器调度。测试执行层封装各种设备驱动包括模拟器驱动、HIL 台架驱动、真车域控制器驱动。智能分析层AI Agent 模块通过工具调用接入编排层完成日志分析、截图判断、失败归因。一条完整链路是这样走的用户在飞书群提及机器人发送“跑一下中控蓝牙的三级页面返回测试”。机器人服务把消息体转发给编排控制层。编排控制层先交给 AI Agent 做意图识别解析出测试范围“中控蓝牙”执行内容“三级页面返回”环境要求“默认环境”。Agent 返回结构化的测试任务定义编排控制层校验后用任务队列排队。调度器从执行器池中分配一个可用的测试执行器下发具体用例列表。执行器在目标设备上运行用例实时上报进度。测试结束执行器把原始日志、截图、通过率和异常项汇总回传。AI Agent 对失败项做分析生成带根因假设的测试摘要。机器人把摘要和关键截图推送到对应飞书群。整个链路里飞书机器人是前台AI Agent 是大脑编排控制层是躯干执行器是手脚。设计上强制要求各层之间只通过结构化协议通信不许相互调用内部方法这是后面能灵活替换执行器或替换模型服务的关键。2.2 测试执行层的设备抽象执行层是最容易出问题的地方。不同设备差异极大模拟器可以随时启停HIL 台架需要预热和信号注入真车域控制器要考虑上电时序和总线通信。我定义了一套设备驱动接口把所有执行器包装起来。核心接口prepare(env)准备环境包括启动模拟器、连接台架或上电。run_case(case_id, steps)执行单条用例。collect_artifact(case_id)收集截图、日志、传感器数据。cleanup()清理环境释放资源。不同的执行器实现类各自封装设备差异。模拟器执行器负责拉起模拟进程、注入刷机镜像台架执行器负责控制继电器上电、等待网络信号就绪真车执行器多一步诊断会话的建立。这样做的好处是编排层完全不需要关心底层设备差异它只认识执行器这个抽象对象。新增设备类型时只需要实现一套驱动注册到执行器池。平台上线后添加过一种测试用的单板机环境前后只花了一个上午接入。用例组织上用了一套轻量标签体系。每条用例除了名称、步骤、预期结果外还挂 module、priority、depends_on、min_env 字段。module 用于按功能模块筛选depends_on 处理前置依赖min_env 约束最低环境。AI Agent 做意图识别时返回的是一组基于标签的筛选条件而不是硬编码的用例 ID 列表这样更灵活。2.3 AI Agent 的能力边界与工具设计AI Agent 是这套平台里最值得讲的部分也是最容易越做越飘的部分。我的原则是Agent 不是来接管测试的它只做两件事——理解用户意图并转化为结构化任务分析结果并给出归因建议。所有最终执行动作都必须在编排控制层里校验Agent 不直接操作设备。Agent 的能力通过对外的工具函数收敛定义了四类query_cases(condition)按条件查询用例返回用例列表和描述。create_test_task(task_json)创建测试任务内部会做参数合法性校验。analyze_log(log_text, case_info)分析日志返回异常摘要和可疑点。analyze_screenshot(image_id, baseline_id)对比截图与基线图返回差异区域。Agent 的大脑部分接的是可插拔的模型服务。模型通过 system prompt 和工具描述知道能做什么、不能做什么。系统提示里明确写了两条硬约束第一只能使用提供的工具不能虚构指令第二对于任何不确定的参数值必须返回 ask_user 请求确认不能自行假设。这里有个细节Agent 返回的意图结果不是自然语言总结而是 JSON 结构。例如{ action: start_test, target: middle_console, module_tags: [bluetooth, back_navigation], env: default, depth: normal, need_confirm: false }编排层拿到 JSON 后会再做一次合法性校验module_tags 是否在字典表里env 是否在环境白名单中。如果 Agent 返回了白名单以外的参数编排层直接拒绝任务并在群里提示参数不在允许范围。这层双保险非常关键踩坑章节再细说。2.4 飞书消息层的闭环设计飞书机器人这边关键是做好消息的双向闭环。用户发指令进来是入口过程中推送状态、结束时推送报告是出口。如果只有入口没有出口机器人就只是个命令转发器。消息类型用了卡片消息。卡片信息密度高可以内嵌按钮、状态标签和图片。机器人服务里维护了一个消息上下文的概念同一用户在同一个群里的请求带上 thread_id用来关联任务和后续状态推送。飞书的事件回调有一个注意点回调可能重复推送。机器人收到回调必须做幂等处理否则一次指令可能触发两遍测试。解决办法是用 Redis setnx 做去重键每个消息唯一 ID 只允许被消费一次过期时间设为五分钟。入口命令的解析并不需要完全依赖 AI。实际设计里用了双通道固定格式的命令比如“跑回归套餐A”走规则引擎直接匹配响应更快非固定格式的自然语言指令才交给 AI Agent 解析。这样减少模型调用量也避免把简单任务复杂化。3. 实际落地关键模块的实现细节3.1 飞书机器人接入与消息处理飞书机器人本质上是飞书开放平台上的一个自建应用。创建应用时开通机器人能力申请对应权限例如发送消息、接收用户消息。拿到 App ID 和 App Secret 后这些信息存到环境变量里不要硬编码在代码中。消息接收方式选了长连接模式。相比 Webhook长连接不用暴露公网地址适合内网部署。SDK 提供长连接事件订阅机制服务启动后自动建立连接事件实时推送省掉了配置回调地址和验证签名这些步骤。机器人服务的核心是一个事件处理循环from lark_oapi.ws import Client as WSClient def handle_message(event): sender event.sender_id if sender not in ALLOWED_USERS: return dedup_key fmsg:{event.message_id} if not redis.set(dedup_key, 1, nxTrue, ex300): return text extract_text(event) task_spec dispatch_parser(text) if task_spec is None: send_card(event.chat_id, 未识别指令请换个说法试试) return enqueue_task(task_spec, thread_idgenerate_thread_id(event)) ws_client WSClient() ws_client.register_event(im.message.receive_v1, handle_message) ws_client.start()消息推送用卡片消息接口。构造卡片时标题部分写任务代号正文部分用 Markdown 渲染执行进度和测试概要底部放两个按钮查看原始日志、重新执行失败用例。按钮回调事件里带上任务上下文 ID用户点击后服务端能找到对应处理动作。一个容易被忽略的细节卡片按钮回调有超时机制必须在数秒内返回一次成功响应否则飞书会认为回调失败并重试。所以按钮触发的后续动作要放进异步队列先立即返回响应再慢慢处理。3.2 AI Agent 工具调用与安全检查Agent 模块用的是一种类似“行动—观察”的循环结构模型接收用户指令和工具描述决定调用哪个工具拿到结果继续推理最后输出结构化 JSON。循环的最大次数设为 5 次超过就终止并提示用户指令过于复杂请拆分。工具注册用注册表模式实现TOOL_REGISTRY {} def register_tool(name): def decorator(func): TOOL_REGISTRY[name] func return func return decorator register_tool(query_cases) def query_cases(condition: dict): return test_repo.query(**condition) register_tool(analyze_log) def analyze_log(log_text: str, case_info: dict): return analyzer.inspect(log_text, case_info)调用 Agent 时工具列表序列化后传给模型同时传入白名单约束只允许调用 TOOL_REGISTRY 中注册过的工具其他函数名一律不接收。模型返回的结果先做 JSON Schema 校验。字段类型、枚举值、必填项都写死校验不过就丢弃输出并要求模型重新生成三次校验不过则整体失败回滚任务。注意一定不能让 Agent 直接持有执行器接口或设备控制权限。Agent 能调用的触发测试工具内部也只是向编排层提交任务后续状态推进完全由编排层接管。这种“Agent 只建议、编排层执行”的模式牺牲了一点端到端智能换来了可控性和可审计性。在车载这些要求高的领域可控永远比炫技重要。3.3 测试任务状态机与调度逻辑编排控制层的核心是一个状态机和一组任务队列。状态机包含INIT任务刚创建参数校验中。QUEUED校验通过等待分配执行器。RUNNING执行器正在跑用例。FINISHED全部执行完成。FAILED任务执行过程中发生不可恢复错误。CANCELED用户主动取消。状态转移只有有限几条路径非法转移直接拒绝并记录日志。任务队列用内存队列加 Redis 持久化重启后能恢复未完成的任务调度信息。并发控制上执行器资源有限。模拟器环境最多跑两路并发再高会把宿主机 CPU 占满影响测试数据。调度器维护每个执行器的当前活跃任务数达到上限就把新任务挂起等待。超时处理最容易疏忽。每条用例预期执行时长不同但必须统一设置硬超时比如单个用例最多 10 分钟整个任务最多 2 小时。超时后执行器强制停止当前操作收集已有日志并打上 timeout 标记。这条在实际运行中特别重要否则遇到某弹窗把流程卡死整个任务就挂住不走了。调度时还会做依赖预检查。用例之间有关联的比如必须先登录再进入设置页调度器会按依赖关系自动排序避免把依赖用例塞到前面。3.4 报告生成与飞书卡片推送测试报告不是简单贴通过率而是要能指导下一步动作。分成三层来组织第一层汇总测试范围、用例总数、通过/失败/阻塞数量、耗时、环境信息。第二层异常列出失败用例及 AI 初步归因标注疑似环境问题、疑似界面行为变更、疑似内存导致卡顿等标签。第三层证据每条失败用例附上截图、日志片段和关键时间戳供人工复核。AI 分析日志时输入的是经过截取的日志关键段落不是全量日志。全量日志动辄几十 MB模型上下文塞不下也没必要。做法是先让执行器对日志做粗筛保留 ERROR 级别、断言失败、设备断开、超时这些关键特征附近的上下文再交给 Agent 分析。省 token归因也更聚焦。报告生成后机器人推送一张摘要卡片到群里带失败截图缩略图。完整 HTML 报告存到内部文件服务卡片上放短链接。实测下来团队里最受欢迎的功能就是失败截图直接出现在群里省去了一层层翻日志的时间。4. 踩坑实录上线后遇到的那些问题4.1 消息重复与乱序的处理上线后遇到的第一个问题是消息重复。飞书事件回调机制在服务端来不及确认时会重发事件导致同一句“跑回归”被执行两次。排查过程不复杂任务日志里同一时间戳出现了两条相同任务基本就能定位。解决办法是消息幂等。每个进站消息都带全局唯一 ID用消息内容和发送时间做哈希在 Redis 里以这个 ID 为键做 setnx只有第一次成功插入的请求才继续处理。重复事件直接丢弃并返回成功响应防止飞书继续重试。另一个问题是乱序。用户连续发两条指令先跑 A 再跑 B如果两条消息被并发处理B 可能先启动。现在编排层按消息时间戳严格排序同一用户的指令按先进先出处理。在处理实时确认卡点前测试任务按创建时间戳升序执行。4.2 AI Agent 参数幻觉的应对Agent 误判是排查中费神最多的。刚开始测试时模型把“跑一下午间测试”理解成“执行一个名叫午间的测试用例集”而用户真实意图是“中午之前跑完”。这类语义歧义很难靠提示词完全消除。后来加了确认机制当 Agent 识别出的参数与常用上下文不一致或者置信度不高时编排层推一张确认卡片列出 Agent 的理解请用户确认后再执行。虽然多一次交互但避免跑错测试带来的更大损失。参数幻觉也是常见问题。模型可能返回不存在的模块标签比如把蓝牙音频写成蓝牙音乐而用例库里只有前者的标签。现在所有 Agent 返回的枚举参数都会经过字典校验不存在的标签直接报错并提示最接近的合法标签列表。实测拦截率接近百分之百因为问题都出在枚举值上而枚举值可以完全规则化。4.3 HMI 设备侧的稳定性问题设备侧的稳定性问题比软件侧更磨人。模拟器启动时长根本不是固定值冷启动有时 30 秒有时 2 分钟。等待时间设太短用例会大面积假失败设太长整个任务周期又被拖长。现在的做法是动态等待加就绪探测。执行器启动环境后不断轮询就绪信号仪表主界面元素是否出现、某个端口是否开始监听、日志里是否打印了进入桌面的关键字。全部就绪才跑用例不靠固定 sleep。实测任务平均耗时反而因为避免了无效重试而缩短了。截图比对也有假性差异问题。HMI 的动效会让控件位置有几像素偏移或者进度动画正好停在中间帧被判定为异常。基线图匹配引入了灰度容忍度和忽略区域列表对时间戳区域、滚动指示条这类动态元素做掩蔽。核心逻辑是帧级差异只能作为疑似项必须配合日志和时间戳才能定级为缺陷还是动效噪声。4.4 部署环境与权限约束车载项目对部署环境要求严格测试平台要求只能运行在公司内网隔离区。这带来两个直接影响飞书官方接口需要域名访问内网环境要走指定的网络出口模型服务也必须部署在内网或者通过合规通道访问。搭建时把这些能力做成独立配置项。飞书接口域名、模型服务地址、文件服务地址全部从配置中心读取部署时可以整体切换。所有对外请求统一走网关出口方便审阅和留痕。权限设计上机器人服务不持有数据库写权限执行器以最小化账号运行只拥有目标设备通信所需的最小权限。这套最小权限原则在回读审计日志时很有帮助能清楚区分哪些动作是任务触发的哪些是人手动操作产生的。4.5 常见问题速查表问题现象可能原因处理办法任务被重复执行飞书事件回调重试对消息 ID 做 Redis 幂等去重用户连续指令乱序并发消费任务队列按消息时间戳排序同一人 FIFOAgent 返回不存在标签枚举参数幻觉字典白名单校验提示最近合法值模拟器首次启动超时冷启动时长不稳定就绪探测轮询代替固定等待截图比对误报动效中间帧导致差异灰度容忍度加忽略区域掩蔽用例卡住不结束弹窗阻塞流程单用例硬超时强制回收回调按钮无响应服务端处理超时立即返回成功异步执行后续逻辑5. 复盘和拓展空间5.1 从“能跑”做到“能解释”平台运行顺畅之后我最大的体会是一套测试平台的价值不在于自动化率多高而在于它在发生了什么、为什么发生、下一步怎么办这三件事上能不能给出让人信服的答案。AI Agent 的价值其实是被逼出来的优先级因为它能缩短从日志到结论的距离而这段距离恰恰是团队协作里最耗时的一环。微调完 Agent 分析提示词让失败摘要里多一句“可能是哪段代码路径导致的”开发同学再也不用把原始日志整个拖进 IDE 一行行翻了。仅这一点就把测试结果从“数据”变成了“建议”使用体验完全不一样。5.2 后续几个想扩展的方向后续值得做的方向有几个。第一是让 AI 直接给出用例修改建议甚至自动生成新用例但前提是积累足够的回归基线来避免误报。第二是把语音交互测试也纳入进来当前平台主要覆盖触控和显示语音回灌测试还没做深度结合。第三是把界面元素定位相关的视觉识别换成更专业的 UI 检测模型而不是通用多模态模型对 HMI 控件的定位精度会有明显提升。目前整个平台还在持续迭代但“对话发起任务、AI 辅助分析、结果回到对话流”这个骨架已经确定下来这套模式不仅适合车载 HMI对其他嵌入式 UI、工业平板、智能座舱领域也有直接参考价值。如果看完你也想动手做类似的东西我的建议是先从最痛的一环入手打通一条最简单的链路再逐步加智能别一开始就把盘子铺太大。