
做了好几年车载 HMI 自动化测试我最大的感受是用例本身不难写难的是整个团队围绕着“跑测试”这件事产生的协作成本。测试机在实验室里人在工位上报告存在服务器里而结论永远要靠人工去催、去问、去截图、去贴群里。每天夜里跑完一轮回归第二天早上还得爬起来整理结果把几十个用例的截图日志塞进文档再挨个 项目组的人来确认。后来我们把飞书机器人拉进了这套体系再让 AI Agent 作为调度大脑搭建了一套车载 HMI 自动化测试平台整个流程才算真正转了起来研发在群里说一句“跑一下主驾屏的蓝牙音乐全流程”飞书机器人收到消息后自动解析意图、分配车机设备、拉起测试用例执行过程中自动抓取截图和 Log跑完以后由大模型归纳出测试结论生成一张带关键证据的可交互卡片推到群里全程不需要任何人打开测试平台后台。这篇文章我就把这套平台的架构设计思路、核心链路、AI Agent 的落地细节和踩过的坑完整写出来希望对做车载测试平台、搞 AI 工程化落地的同学有些实际参考。1. 为什么是“飞书机器人 AI Agent”而不是传统测试平台先聊一个容易被忽略的问题我们已经有了自动化测试框架为什么还要做一层机器人入口因为传统测试平台的核心模型是“人找任务”任务界面挂在 Web 后台用户要先登录、再选项目、再挑设备、再点执行执行完了跳到报告页找结论。这个链路在每天高频沟通的场景下非常割裂。研发问一句“昨晚回归怎么样”我得先去服务器翻报告再把关键信息从几十页日志里摘出来最后贴到群里——中间每一个环节都在消耗注意力。飞书机器人的价值在于把“测试能力”搬进了团队日常沟通的发生地。群里天然有上下文这条测试是哪款车型、哪个屏幕、哪个版本固件、谁发起的都能从会话里带出来。研发不用学平台操作不用等测试同学转述消息本身就是指令回执本身就是答案。那为什么还要引入 AI Agent而不是写一套固定关键词的指令机器人我早期试过后者规则写出来又长又脆。用户说“跑蓝牙”和“验证一下蓝牙音乐播放有没有问题”在意图上是同一件事但正则或关键词匹配根本没法优雅处理这种表达差异。AI Agent 的优势是它能理解自然语言变体并且能把需求拆成一组可执行的动作序列——比如先检查设备在线再拉起主驾屏唤醒流程再进入蓝牙音乐页再执行播放校验。这本质上是一个“任务规划器”。所以这个组合的本质是飞书机器人负责“入口和反馈”AI Agent 负责“理解和编排”自动化测试框架负责“真正的执行”。三者各干各的边界清晰这也是它能稳定落地的前提。2. 整体架构设计一条消息总线串起四个核心模块整个平台从逻辑上分成四层飞书机器人网关、AI Agent 编排层、测试执行引擎、结果与数据服务。这四层之间通过统一的消息通道连接任务请求和回执都用同一种带 trace id 的消息结构。飞书机器人网关是整个平台的入口负责接收群聊消息、解析回调动作、发送富文本卡片。它不处理任何业务逻辑只做消息的鉴权、格式转换和路由。AI Agent 编排层是决策中心接收到用户指令后它会调用大模型将指令拆解为工具调用序列然后通过函数调用机制触发具体动作。这里我把每个测试能力都封装成了工具函数Agent 只负责选哪个工具、填什么参数、按什么顺序调用。测试执行引擎承接 Agent 编排层发来的执行请求它管理着一批车机设备或模拟器实例内部包含用例仓库、执行器、截图服务、日志采集模块和电源控制模块。真正跑用例的是这一层。结果与数据服务负责存储执行记录、截图、指标数据和 AI 分析报告同时对外提供查询接口让飞书卡片能回填进度和结论。模块关键组件核心职责飞书机器人网关消息接收、卡片交互群聊指令输入、结果推送、人工确认AI Agent 编排层意图解析、工具调度、上下文管理将自然语言转成可执行工具链测试执行引擎设备管理、用例引擎、日志采集调用车载 HMI 自动化测试框架真实执行结果与数据服务报告生成、指标存储、AI 分析汇总证据、生成结论、回传飞书这个分层设计解决了几个实际问题。一是解耦机器人网关可以批量替换比如以后从飞书切到其他 IM 工具只改网关层就行AI Agent 和执行引擎完全不受影响。二是可观测由于所有模块都走统一消息通道每一步都有 trace id出了问题能沿着链路追到具体环节。三是安全边界AI Agent 不直接碰设备它只能通过工具函数间接下发指令这等于给大模型上了一道“物理约束”。我记得早期设计时曾纠结要不要把所有模块揉进一个服务里看起来开发快实际上后面每次改动都要碰核心链路。后来强制拆开虽然多写了一些接口但扩展效率反而高了很多。3. 核心链路拆解一条自然语言指令如何变成一次 HMI 用例执行这条链路是整个平台最核心的部分。我把它拆成七个环节每个环节都有明确的输入输出和边界条件。第一步用户在飞书群内发出一条消息比如“在舒适型 HMI 版本上跑一遍主驾屏蓝牙音乐的回归”。飞书机器人通过事件订阅机制收到消息先做基础校验发送者是否在可用白名单内、群组是否授权、消息格式是否为文本。校验通过后生成一个全局唯一的 trace id把原始消息和发送者信息封装成标准任务消息投递到消息通道。第二步AI Agent 编排层消费这条任务消息。它先从消息中提取关键槽位目标车型、HMI 版本、屏幕区域、功能模块、测试范围。提取过程依赖大模型但为了防止幻觉我给 Agent 提供了一个“槽位校验器”——每个槽位都必须命中预定义的枚举值比如车型只能从“舒适型/旗舰型/运动型”里选功能模块只能从“蓝牙音乐、导航、语音助手、车辆设置”等白名单里选。如果槽位无法对齐Agent 不会强行执行而是通过飞书卡片向用户发起确认。第三步Agent 把确认后的槽位转换为一个结构化的测试任务描述包含用例范围、设备需求、执行参数和预期产物。这里需要说明的是Agent 不直接生成测试代码它只做任务描述和编排。真正落到车机上的自动化逻辑仍然由人力编写的用例脚本承担。这样做的好处是风险可控——大模型跑偏的代价被限制在“参数填错”这个层面而不至于生成一段不可控的测试代码去操作真车屏幕。第四步测试执行引擎收到任务后先做资源调度。它检查目标屏幕上是否有空闲设备如果没有任务进入队列等待。随后引擎根据任务描述筛选用例集组装执行上下文通过 adb / 车机私有协议连接设备开始执行。第五步执行过程中引擎主动采集三类证据屏幕截图、UI 层级文本、系统 Log。在车载 HMI 场景里证据比结果重要得多。一个用例断言失败了如果没有截图和日志根本没法定位是车机卡顿、网络波动、还是固件 bug。所以执行器在每个用例的关键节点都会打点并同步采集证据而不是等失败了再补抓。第六步执行结束后引擎把原始结果送入结果与数据服务。AI Agent 的分析任务此时被再次唤醒——它拿到完整的执行记录开始生成测试摘要。注意这里的“分析”不是简单地把通过/失败数量列出来而是要结合失败截图和关键日志给出初步原因分类。比如某用例失败是因为页面元素未加载Agent 会把截图上的文字和 UI 层级文本拼进 Prompt让大模型判断失败类型再在卡片中输出“疑似控件加载超时建议检查网络代理设置”这样的初步定位结论。第七步飞书机器人把 AI 摘要以可交互卡片的形式推到群里。卡片里包含测试结论、通过率、关键失败项截图、日志片段链接还有一个“查看详情”按钮。点击按钮会触发 card callback机器人再拉起报告页或者把完整日志推送到当前会话。这里有一个很容易被忽略的设计点飞书卡片的消息格式不要设计成一次性推送到底而是先用一个“任务已接收”的轻量卡片反馈给用户后面再更新卡片内容。因为长任务执行时间往往超过几秒如果请求界面一直干等用户会以为消息丢了。我们采用的是“先确认后执行”用户看到“任务已进入队列”这个回执就知道指令被系统吃进去了后面再异步推送最终结果。4. AI Agent 的“工具编排”设计如何既聪明又可控AI Agent 在这套平台里不是聊天机器人它更像一个“会调用 API 的调度员”。为了让这个大模型按规矩办事我把所有测试能力封装成工具函数每个工具都有明确的名称、参数描述和调用约束。Agent 通过函数调用机制来选择工具而不是自由发挥。举个例子我定义的工具集合大致是TOOLS [ { name: find_device, description: 查询当前空闲的车机测试设备, parameters: { type: object, properties: { screen: {type: string, enum: [主驾屏, 副驾屏, 后排屏, 中控屏]}, variant: {type: string, enum: [舒适型, 旗舰型, 运动型]} }, required: [screen, variant] } }, { name: run_test_suite, description: 执行指定功能模块的自动化用例集, parameters: { type: object, properties: { module: {type: string, enum: [蓝牙音乐, 导航, 语音助手, 车辆设置]}, suite: {type: string, enum: [冒烟, 回归, 全量]}, device_id: {type: string} }, required: [module, suite, device_id] } }, { name: fetch_execution_result, description: 查询某次任务执行的原始结果与证据文件, parameters: { type: object, properties: { trace_id: {type: string} }, required: [trace_id] } } ]这套设计有几个关键决策。第一个是参数枚举优先。能枚举的字段绝不让大模型自由发挥。比如测试范围只允许冒烟、回归、全量三选一车型、屏幕也都是白名单。这样即使模型意图理解错了错误也会被限制在可控范围内最多跑错一个小集合不会出现它自己发明一个模块名导致用例引擎直接崩掉的情况。第二个是工具链编排要可回放。每当 Agent 完成一次任务规划我们都会把“用户原始消息 工具调用序列 最终结论”完整保存下来。这些数据后续有两个用途一是作为审计日志一旦出现问题可以回放整个决策过程二是作为少样本示例沉淀下次类似指令出现时可以把历史成功链路作为参考放进 Prompt提升意图理解的稳定性。第三个是人工确认兜底。我特别注意了高风险操作的二次确认机制。比如“恢复出厂设置”“升级固件”“全量回归”这类影响面很大或耗时很长的操作Agent 调用前必须先返回一个确认卡片用户点击“确认执行”后工具链才会真正触发。AI 足够聪明但测试设备是实打实的硬件资源一次错误的全量回归可能浪费整个团队半天时间。还有一点关于 Prompt 的细节值得说。AI Agent 的系统提示词里不要只写“你是测试助手”要给它完整的角色边界说明。我们实际使用的系统提示词里明确写了三条约束第一所有动作必须通过工具函数发起禁止生成不回传的动作指令第二如果用户指令模糊必须主动发起确认而非猜测第三涉及设备操作时必须检查设备是否在线。这看起来像是常识但没有这三条边界大模型就会频繁出现“自说自话地执行假设任务”这种致命问题。我在最初版本里吃过亏。当时 Agent 把“跑一下蓝牙的用例”理解成了“跑所有蓝牙相关用例”结果它自己拆成了十几个子任务全部排队执行整整占了三台测试设备一上午。后来加上参数枚举和范围确认类似问题基本绝迹。5. 车载 HMI 自动化测试的工程化难题平台是怎么兜住的车载 HMI 测试和普通的 App 测试差别很大很多坑不在用例逻辑上而在硬件和环境的不可控上。这套平台如果要长期稳定运行必须在工程化层面把这些“环境噪声”先解决掉。第一是设备稀缺且昂贵。一个测试团队可能只有几台真实车机或域控制器用例多的时候调度竞争非常激烈。平台因此实现了设备池机制每台设备都有状态标记空闲、占用、维护、离线。任务调度时会自动选择空闲设备如果全部占用就按优先级和创建时间排入队列。设备管理器还会定期发送心跳检查一旦发现设备无响应自动触发重启流程并在飞书群里通知管理员。第二是车机屏幕的差异化。不同车型的中控屏分辨率不同、布局不同、深色浅色模式也不同同一个“蓝牙音乐入口”在不同屏幕上控件位置可能完全不同。自动化测试脚本如果写死了坐标换台设备就跑挂。平台的做法是把“控件定位”和“用例逻辑”分层脚本通过 UI 层级属性和语义标签定位控件只有实在拿不到语义属性的场景才允许使用相对坐标。第三是执行过程中车机可能自己“睡”过去。HMI 设备如果长时间没有交互屏幕会自动熄屏进入低功耗模式导致后续用例全部失败。执行器里因此加了一个看门狗任务在用例间隔空闲时模拟一次轻量交互保持屏幕活跃状态。这个改动很小但直接让夜间长时间回归跑批的成功率提升了一截。第四是日志和截图的闭环。车载测试里失败用例的调试成本通常远高于执行成本。平台会为每次用例执行保留完整时间线启动参数、每个步骤的截图、UI 层级快照、系统 Log。AI Agent 做失败分析时也是喂这些数据而不是只看一个断言布尔值。如果分析结果显示控件加载超时日志片段会直接链接出来研发拿到群里就能定位不再需要重新复现。这些工程化细节本质上都是在为 AI Agent 提供“干净的上下文”。模型分析再强如果喂给它的日志是零散的、丢失时间戳的结论也一定不可靠。所以平台在数据采集层花了不少功夫尽量做到“一次执行全量可溯”。6. 落地过程中的典型问题与调优实录这套平台不是一次写成的中间翻了好几个车。说三个最有代表性的问题每个都花了不少时间排查和调优。第一个问题是 AI Agent 意图误判导致执行范围失控。上线第一周有研发在群里说“先冒烟一下”Agent 把“冒烟”正确解析成了冒烟测试集但它同时自作主张追加了“再看一下回归结果”结果触发了一轮完整回归整整跑了一晚上。后来在 Prompt 里加了“只执行用户明确要求的动作禁止追加未提及的动作”同时在工具层给 suite 参数加默认值确保只有显式确认后才能跑全量回归。这类问题在 AI 场景里特别典型不是模型不够聪明而是它“太想帮人把事做全了”。第二个问题是长任务执行时的通道断裂。最初飞书机器人收到指令后是同步等待执行结果的但车载用例动辄跑十几分钟HTTP 连接早就超时断开了用户收不到回执。后来改成异步模式机器人先把任务投入队列立刻回传“已受理”卡片任务执行完成后通过消息通道主动推送结果。所有涉及长耗时操作的工具函数都统一走这个异步链路。第三个问题是跨模块日志串联困难。早期每个模块各自打印日志同一个任务在机器人网关、AI Agent、执行引擎里留下了三段互不关联的记录排查问题非常痛苦。后来强制规定了 trace id 从消息入口开始生成、贯穿全链路所有模块在打印日志、上传证据、回传统计时都必须携带这个 id。现在无论用户在群里反馈什么问题我们只要拿到 trace id就能翻出整条链路的详细时间线。现象排查思路最终方案AI 主动追加未要求的测试任务回放 Agent 工具链日志发现模型提前访问了执行接口并补充参数Prompt 追加执行边界约束工具参数改为显式白名单高风险任务加人工确认长任务执行期间用户收不到回执检查网关日志确认是同步等待超时导致连接断开改为异步任务模型先回“已受理”执行完成后主动推送结果卡片同一任务三段日志无法关联对比各模块日志发现缺少全局唯一标识入口统一生成 trace id全链路强制透传这三个问题解决了以后平台才真正从“能跑”变成“好用”。现在群里跑一轮回归研发看到的不只是通过率数字而是能直接展开关键失败截图、看到 AI 初步定位结论、顺着日志链接点进详情。整个闭环下来测试同学不需要再频繁催结果研发同学也不需要再干等报告。7. 边界感与个人体会AI Agent 不是替代自动化而是让它更好用最后聊一点个人感受。这套平台上线一段时间后我的一个核心体会是AI Agent 在测试领域的价值不在于它能“写用例”或“替代测试工程师”而在于它把已有测试资产变成了一种团队可以随时调用的服务。车机测试的难点从来不只是技术实现更是人机协作的效率问题——以前跑一个用例要跑到实验室、盯设备、收日志现在群里说一句话剩下的事情由机器人接管这种体验变化是实打实的。当然边界也在逐渐清晰。AI Agent 可以做任务编排、结果摘要、初步失败分类但它暂时不适合直接修改测试用例代码也不适合在设备状态异常时自行决策重启车辆系统。这些边界我建议团队在设计平台时就用工具权限和人工确认机制彻底锁死不要把控制权满天飞地放给模型。如果你也在做类似的事情我的建议是先跑通一条最小闭环再扩展不要一上来就追求大而全。先让机器人能接收指令、跑一个模块的用例、推一张结果卡片这个闭环的价值已经很大了。然后再逐步加入 AI 意图解析、自动设备调度、失败日志分析这些增强能力。毕竟 AI Agent 的加入是让测试平台“长脑子和长嘴”但真正干活的双手还是那套已经稳定运行了很久的自动化测试脚本。把这套基础打牢AI 才能在上面发挥出真正的作用。