1. 移动端自动化测试的现状与ARTEMIS的切入点移动端自动化测试这件事做过的人都懂它跟Web端完全不是一个难度量级。Web端你至少有一个相对统一的DOM树可以抓有稳定的选择器可以定位浏览器DevTools一开元素、网络、控制台全都摆在明面上。但移动端呢原生控件体系碎片化、渲染管线不透明、不同系统版本行为差异巨大再加上真机与模拟器的表现不一致导致很多团队在移动端自动化上的投入产出比一直很难看。我最早接触移动端自动化是在一个跨平台应用的项目里当时用的是传统的UI测试框架脚本写了几百条维护成本高得离谱。每次应用改版选择器大面积失效测试脚本的修复时间甚至超过了手工回归的时间。后来大语言模型的能力上来了我开始琢磨能不能用LLM来做移动端的自动化测试让模型去理解界面、生成操作序列、甚至自主判断测试结果。这个方向探索了一段时间之后我注意到一个叫ARTEMIS的方案它提出的双模式架构让我眼前一亮。ARTEMIS这个名字本身是“Automated Reasoning and Testing for Mobile Interface Systems”的缩写从命名就能看出来它是专门针对移动端界面系统的自动化推理与测试框架。它最核心的设计就是双模式架构——一套系统里同时支持两种截然不同的工作模式分别应对移动端自动化测试中两类本质不同的任务场景。这个思路解决了我之前一直纠结的一个问题到底应该让LLM做“理解型”的工作还是“执行型”的工作ARTEMIS的答案是两者都要但要用不同的模式来承载。这篇文章我会从架构设计的角度把ARTEMIS的双模式拆开来讲清楚。包括它为什么这么设计、两种模式各自解决什么问题、底层是怎么实现的、实际跑起来效果如何、有哪些坑需要注意。如果你正在做移动端自动化测试或者正在探索LLM在测试领域的落地这篇内容应该能给你不少参考。2. 双模式架构的整体设计思路2.1 为什么单一模式走不通在聊ARTEMIS的双模式之前得先说说为什么单一模式在移动端自动化测试里走不通。我试过两种极端方案都碰了壁。第一种是纯脚本驱动模式。就是传统的做法测试人员写好每一步操作LLM只负责在脚本失败的时候帮忙分析一下日志。这种模式的问题在于移动端界面的变化太频繁了脚本的脆弱性极高。一个按钮从左上角挪到右下角或者文案从“确认”改成“确定”脚本就挂了。LLM在这里只是个事后诸葛亮帮不上实质性的忙。第二种是纯LLM自主模式。让LLM看着屏幕截图自己决定下一步点什么。听起来很美好但实际跑起来问题一大堆。首先是延迟每次操作都要调一次模型推理一个完整的测试用例跑下来要几分钟甚至十几分钟。其次是稳定性LLM有时候会“幻觉”点到一个不存在的控件上或者陷入循环操作。最后是成本高频调用大模型的费用不是每个团队都能承受的。ARTEMIS的设计者显然也踩过这些坑所以他们的双模式架构本质上是在确定性与灵活性之间找平衡。一种模式负责处理那些结构清晰、流程固定的测试场景追求的是速度和稳定性另一种模式负责处理那些需要理解、推理、探索的复杂场景追求的是覆盖度和智能性。两种模式共享同一套底层能力但在调度策略、推理深度、执行方式上做了明确的区分。2.2 两种模式的分工逻辑ARTEMIS把两种模式分别叫做Direct模式和Agentic模式。名字很直白Direct就是直接执行Agentic就是智能体式的自主执行。Direct模式的核心思路是“预编译轻量推理”。测试人员或者上游系统提供结构化的测试意图描述ARTEMIS把它编译成一套可执行的操作序列然后在执行过程中用轻量级的视觉匹配来定位控件。这里的LLM参与度很低主要用在两个环节一是把自然语言描述的测试意图转成结构化指令二是在视觉匹配失败的时候做一次兜底判断。整个执行过程是确定性的速度快资源消耗低。Agentic模式则是“感知-推理-行动”的闭环。LLM在这里是核心决策者它看着当前屏幕的截图结合测试目标自主决定下一步该做什么操作。这个模式适合处理那些流程不固定、需要探索的测试场景比如“遍历应用的所有设置项检查是否有崩溃”这种任务。Agentic模式的单步延迟高但它的优势在于能处理Direct模式搞不定的复杂情况。这两种模式不是互斥的而是互补的。ARTEMIS的调度层会根据测试任务的特征自动选择模式也支持在同一个测试用例里混合使用。比如一个测试用例的前半段是固定的登录流程用Direct模式快速跑完后半段是探索性的功能验证切换到Agentic模式。这种灵活性是ARTEMIS相比其他方案的一个明显优势。2.3 共享底层能力的架构分层虽然两种模式的工作方式差异很大但ARTEMIS在架构上做了很好的抽象让它们共享了大量的底层能力。整个系统大致分为四层层级职责两种模式的差异感知层截图采集、UI树解析、控件识别共享但Agentic模式需要更丰富的感知信息推理层LLM调用、提示词管理、结果解析Direct模式用轻量推理Agentic模式用完整推理链执行层操作指令下发、设备控制、异常处理Direct模式批量执行Agentic模式单步执行调度层模式选择、任务编排、状态管理核心差异层决定何时用哪种模式这个分层设计的好处是感知层和执行层的代码只需要维护一份两种模式的差异被收敛在推理层和调度层。我在自己搭建类似系统的时候一开始没有做这种抽象结果两套逻辑各写各的维护起来非常痛苦。ARTEMIS的这个设计值得借鉴。感知层里有一个细节值得说就是UI树的获取方式。Android端通过无障碍服务拿到的UI树信息最全但有些应用会做反自动化处理导致UI树不完整。iOS端的情况更复杂XCUITest提供的元素信息有限。ARTEMIS的做法是UI树和截图双通道并行UI树能拿到就用UI树做精确定位拿不到就用视觉模型做兜底。这个双通道策略在实际项目里非常实用。3. Direct模式的实现细节与实操要点3.1 测试意图的结构化描述Direct模式能不能跑得快、跑得稳关键看测试意图描述得够不够结构化。ARTEMIS定义了一套DSL用来描述测试步骤。这套DSL不复杂核心就是几个要素操作类型、目标控件、操作参数、预期结果。举个例子一个登录操作的DSL描述大概长这样step: login actions: - type: input target: text: 用户名输入框 locator_hint: resource_id:username_field value: test_user - type: input target: text: 密码输入框 locator_hint: resource_id:password_field value: test_pass - type: click target: text: 登录按钮 locator_hint: text:登录 expect: - type: element_visible target: text: 首页这里有个设计细节值得注意locator_hint字段。它不是强制性的精确定位符而是一个提示。ARTEMIS在执行时会优先用这个提示去找控件如果找不到再启动视觉匹配。这种“提示兜底”的设计比传统的硬编码选择器灵活得多。我在自己的项目里也采用了类似的做法把resource_id、text、content_description都作为候选提示命中率明显提升。DSL的编写可以由人工完成也可以由LLM从自然语言测试用例自动生成。ARTEMIS提供了一个转换工具输入是自然语言描述的测试步骤输出是DSL。这个转换过程用的就是LLM但只做一次生成的DSL可以复用。这比每次执行都调LLM要经济得多。3.2 视觉匹配的轻量推理策略Direct模式在执行时如果locator_hint没能命中控件就会启动视觉匹配。这里的视觉匹配不是让LLM直接看截图找控件那样太慢。ARTEMIS用的是一个两阶段策略。第一阶段是传统CV匹配。用模板匹配、特征点匹配这些经典方法在截图里找和预期控件相似的区域。这一步很快毫秒级。如果匹配度超过阈值直接返回坐标。大部分情况下这一步就能解决问题因为移动端界面的控件外观变化通常不会太剧烈。第二阶段才是LLM辅助判断。当传统CV匹配的置信度不够时把截图和控件描述一起发给LLM让LLM判断控件的位置。这里的提示词设计很关键ARTEMIS用的是“网格定位法”把截图划分成N×M的网格让LLM输出控件所在的网格编号而不是直接输出像素坐标。这样做的好处是降低了LLM的输出空间提高了准确率。我实测下来网格定位法比直接输出坐标的准确率高出不少尤其是在控件较小或者界面较复杂的情况下。实操心得网格的粒度需要根据屏幕分辨率调整。1080P的屏幕用6×10的网格比较合适太粗了定位不准太细了LLM容易搞混。另外在提示词里明确告诉LLM“只输出网格编号不要输出其他内容”能进一步降低解析失败的概率。3.3 批量执行与异常恢复机制Direct模式的一个核心优势是支持批量执行。因为操作序列是预编译好的ARTEMIS可以一次性把多个操作下发给设备而不是一步一步等。这在Android上通过UiAutomator的批量操作接口实现在iOS上通过XCUITest的批量命令实现。批量执行能把测试速度提升30%到50%具体取决于操作的类型。但批量执行也带来了一个问题异常恢复。如果批量操作中间某一步失败了后面的操作可能全部错位。ARTEMIS的解决方案是在每个操作之间插入状态检查点。检查点不执行实际操作只是快速验证当前界面是否符合预期。如果检查点失败就中断批量执行回退到单步模式重新定位控件后再继续。这个机制听起来简单但实现起来有不少细节。比如检查点的验证逻辑要足够轻量不能拖慢整体速度检查点的频率要合理太密了影响性能太疏了异常发现不及时。ARTEMIS默认是每3到5个操作插入一个检查点这个频率在实际项目里比较平衡。异常恢复还有一个重要的策略是重试与降级。当某个操作失败时ARTEMIS会先重试一次重试时换一种定位方式比如从resource_id换成text。如果还失败就降级到Agentic模式让LLM来接管这一步。这种“Direct优先Agentic兜底”的策略既保证了大部分场景的速度又保证了复杂场景的覆盖率。4. Agentic模式的推理闭环与执行策略4.1 感知信息的组织与提示词设计Agentic模式的核心是让LLM根据当前屏幕状态自主决策。这里第一个要解决的问题是给LLM看什么。只给截图只给UI树还是两者都给ARTEMIS的做法是截图为主UI树为辅。截图提供视觉信息UI树提供结构信息。但两者不能简单拼接因为UI树的信息量可能非常大全部塞进提示词会超出上下文窗口。ARTEMIS用了一个信息压缩的策略从UI树里提取出可交互的控件列表每个控件只保留类型、文本、位置、是否可点击这几个关键属性然后以简洁的格式呈现给LLM。提示词的结构大致是这样的当前屏幕截图[图片] 可交互控件列表 1. 按钮 登录 位置(500,1200) 可点击 2. 输入框 用户名 位置(300,800) 可输入 3. 文本 忘记密码 位置(700,1300) 可点击 ... 测试目标完成登录流程 历史操作已输入用户名已输入密码 请决定下一步操作输出格式{action: click, target: 登录}这个提示词设计有几个讲究。第一控件列表用编号而不是坐标让LLM输出编号减少输出错误。第二包含历史操作避免LLM重复执行已经做过的操作。第三输出格式固定为JSON方便程序解析。第四测试目标要明确LLM需要知道它要达成什么才能做出合理的决策。注意事项提示词里的控件列表顺序会影响LLM的决策。我试过按位置从上到下排序也试过按重要性排序实测下来按位置排序更符合LLM的“阅读习惯”决策准确率略高。另外控件列表不要超过20个太多了LLM会“看花眼”需要做截断或者分页。4.2 行动空间的约束与安全边界让LLM自主操作移动设备听起来很酷但风险也很大。如果LLM决策失误可能会点到不该点的地方比如删除数据、发送消息、产生费用。ARTEMIS在Agentic模式里设置了多层安全边界。第一层是操作白名单。只有白名单里的操作类型才允许执行比如click、input、swipe、back。像“卸载应用”“清除数据”这类危险操作默认被禁用。第二层是控件黑名单。某些控件被标记为不可操作比如“删除”“支付”“退出登录”这些。黑名单可以由测试人员配置也可以由系统根据控件文本自动识别。第三层是操作频率限制。同一个控件在短时间内被连续点击超过N次就触发熔断暂停Agentic模式转人工确认。这个机制能有效防止LLM陷入循环。第四层是敏感操作二次确认。对于输入密码、点击支付按钮这类操作ARTEMIS会先截图存档再执行操作方便事后审计。这些安全边界在实际项目里非常必要。我在早期实验里就遇到过LLM反复点击同一个按钮的情况因为没有频率限制白白浪费了好几分钟的推理时间。加上熔断机制之后这类问题基本消失了。4.3 多步推理与状态追踪Agentic模式的另一个难点是多步推理。一个复杂的测试任务可能需要几十步操作LLM需要记住之前做了什么、当前处于什么状态、下一步该做什么。ARTEMIS用了状态机记忆摘要的方式来管理。状态机定义了测试任务的关键状态节点比如“未登录”“已登录”“在首页”“在设置页”。每次操作后ARTEMIS会根据当前界面判断处于哪个状态并更新状态机的状态。如果状态偏离了预期路径就触发告警。记忆摘要则是把历史操作压缩成简短的文本塞进提示词里。比如“已输入用户名已输入密码已点击登录按钮当前在首页”。这样LLM不需要看完整的历史记录就能知道当前进展。摘要的生成也是用LLM做的但用的是小模型成本很低。这个状态追踪机制还有一个好处是支持断点续测。如果测试中途因为网络问题或者设备问题中断了ARTEMIS可以根据状态机的记录从断点处继续执行而不需要从头再来。这在跑长流程测试用例的时候非常实用。5. 两种模式的调度与协同机制5.1 模式选择的决策依据ARTEMIS的调度层负责决定什么时候用Direct模式什么时候用Agentic模式。这个决策不是随机的而是基于几个明确的依据。第一个依据是测试任务的确定性。如果测试步骤是预先定义好的、流程固定的就用Direct模式。如果测试任务是探索性的、需要根据界面反馈动态调整的就用Agentic模式。第二个依据是界面的稳定性。如果目标应用的界面结构稳定、控件定位容易Direct模式就够了。如果界面变化频繁、控件难以定位Agentic模式的适应性更强。第三个依据是性能要求。如果测试用例需要在短时间内跑完比如CI流水线里的冒烟测试优先用Direct模式。如果对时间不敏感比如夜间的全量回归可以用Agentic模式做更深入的探索。第四个依据是历史执行数据。ARTEMIS会记录每个测试用例的历史执行情况如果某个用例用Direct模式经常失败调度层会自动切换到Agentic模式。这种基于数据的自适应调度比人工配置要智能得多。5.2 混合执行的实际案例我拿一个电商应用的测试用例来举例说明混合执行是怎么工作的。这个测试用例的目标是“验证用户从搜索商品到下单的完整流程”。整个流程可以拆成几个阶段阶段一登录。这是固定流程用Direct模式。输入用户名密码点击登录验证首页出现。整个过程5秒内完成。阶段二搜索商品。搜索关键词是固定的但搜索结果列表的排序可能变化。这里用Direct模式输入关键词但点击哪个商品用Agentic模式决策因为需要根据商品名称、价格、评分来选择。阶段三加入购物车。这是固定流程用Direct模式。点击加入购物车按钮验证购物车数量变化。阶段四结算下单。结算流程涉及地址选择、支付方式选择、优惠券选择这些选项的状态可能因用户账号而异。这里用Agentic模式让LLM根据当前页面状态自主决策。阶段五订单验证。验证订单是否创建成功用Direct模式检查订单列表。这个混合执行的方案比全程用Direct模式覆盖率更高比全程用Agentic模式速度快了将近一倍。ARTEMIS的调度层会自动做这种拆分测试人员只需要描述测试目标不需要手动指定每个阶段用什么模式。5.3 模式切换的触发条件与开销模式切换不是没有代价的。从Direct切到Agentic需要重新初始化Agentic模式的上下文包括加载提示词模板、建立状态机、采集当前屏幕信息。这个开销大概在1到2秒。从Agentic切回Direct开销小一些主要是保存Agentic的状态和清理上下文。ARTEMIS在调度时会把切换开销考虑进去。如果预计Agentic模式只需要执行一两步就切回Direct那可能不划算不如全程用Direct加视觉兜底。调度层有一个简单的成本模型估算两种模式的预期耗时选择总耗时更低的方案。实操心得模式切换的频率不宜过高。我见过一个配置每个操作都在两种模式之间切换结果切换开销占了总时间的40%。后来把切换粒度调整为“按阶段切换”性能明显改善。建议在测试用例设计阶段就规划好模式的使用而不是完全依赖调度层的动态决策。6. 实际部署中的常见问题与排查技巧6.1 设备兼容性问题移动端自动化测试绕不开设备兼容性。ARTEMIS虽然做了抽象但不同设备、不同系统版本的表现还是有差异。我整理了几个常见问题和应对方法。问题现象可能原因解决方法截图黑屏设备开启了安全模式或DRM保护关闭安全模式或改用UI树定位控件坐标偏移屏幕分辨率或密度与预期不符在配置里显式指定分辨率和密度输入文字乱码输入法不兼容或编码问题改用ADB直接输入或切换输入法操作延迟高设备性能不足或后台进程干扰关闭后台应用降低截图质量无障碍服务断开系统回收了服务增加心跳检测自动重连设备兼容性问题的排查最有效的方法是保留现场。ARTEMIS在每次操作失败时都会自动保存截图、UI树、日志方便事后分析。我建议把这些现场数据按测试用例和时间戳组织好出问题的时候能快速定位。6.2 LLM推理的稳定性问题Agentic模式依赖LLM推理而LLM的输出不是100%稳定的。同样的输入可能这次输出正确下次就输出错误。ARTEMIS用了几个策略来提升稳定性。温度参数调低。Agentic模式的LLM调用温度设置为0.1到0.3减少随机性。但温度也不能太低太低了LLM会变得“死板”遇到稍微不同的情况就不知道怎么办。输出格式校验。LLM的输出必须符合预定义的JSON格式不符合就重试。重试时会在提示词里加上“上次输出格式错误请严格按照JSON格式输出”的提醒。多候选投票。对于关键决策ARTEMIS会调用LLM三次取多数结果。这个策略能把决策准确率提升5到10个百分点但成本也翻了三倍。一般只在关键步骤上用。规则兜底。如果LLM连续多次输出无效结果就降级到规则引擎用预定义的启发式规则做决策。虽然不够智能但至少能保证测试继续跑下去。6.3 测试脚本的维护策略不管是Direct模式还是Agentic模式测试脚本的维护都是个长期工作。ARTEMIS在这方面提供了一些辅助功能但工具只是辅助关键还是要有好的维护策略。我的经验是分层维护。把测试脚本分成三层基础操作层、业务逻辑层、测试用例层。基础操作层封装点击、输入、滑动这些原子操作这部分最稳定很少改动。业务逻辑层封装登录、搜索、下单这些业务动作应用改版时可能需要调整。测试用例层是具体的测试场景变化最频繁。ARTEMIS的DSL支持这种分层可以在DSL里引用其他DSL片段。这样应用改版时只需要修改业务逻辑层的DSL测试用例层不用动。这个设计能大幅降低维护成本。另外定期回归很重要。我建议每周跑一次全量回归及时发现因为应用更新导致的脚本失效。ARTEMIS的调度层会根据历史数据自动标记“脆弱”的测试用例这些用例需要优先检查和修复。7. 性能优化与成本控制的实战经验7.1 截图与UI树采集的优化截图和UI树采集是移动端自动化测试里最频繁的操作优化这两项能显著提升整体性能。截图的优化点主要有三个。第一是降低截图质量。Agentic模式用的截图不需要原图压缩到70%质量、缩放50%大小LLM照样能看懂但传输和处理时间能减少一半以上。第二是增量截图。如果两次截图之间界面变化不大只传输变化区域。这个需要设备端支持Android的MediaProjection API可以实现。第三是截图缓存。同一个界面状态下的截图只采集一次后续复用。UI树的优化主要是裁剪。完整的UI树可能包含几百个节点但真正有用的可交互控件可能只有十几个。ARTEMIS在采集UI树后会做一次过滤只保留可点击、可输入、可滚动的节点以及它们的父节点。这样UI树的大小能减少80%以上。7.2 LLM调用的成本控制Agentic模式的成本主要来自LLM调用。控制成本有几个实用的方法。用小模型做粗筛。不是所有决策都需要大模型。ARTEMIS先用一个小模型比如7B参数级别的做初步决策如果小模型的置信度高于阈值就直接采用如果置信度低再调用大模型。这个策略能在保证准确率的前提下把大模型调用量减少60%以上。缓存决策结果。相似的界面状态和测试目标决策结果往往是一样的。ARTEMIS会把决策结果缓存起来下次遇到相似情况直接复用。缓存的key是界面特征的哈希值相似度匹配用向量检索。批量推理。如果多个测试用例同时跑可以把它们的LLM调用合并成一批一次性发给模型。批量推理的吞吐量比单条调用高得多成本也更低。设置预算上限。每个测试用例设置一个LLM调用次数上限超过了就降级到Direct模式或者直接失败。这个机制能防止某个用例因为LLM陷入循环而烧掉大量预算。7.3 并行执行与资源调度移动端自动化测试通常需要多台设备并行跑才能满足CI的时间要求。ARTEMIS支持多设备并行但并行也带来了资源调度的问题。设备分配策略。ARTEMIS会根据测试用例的设备需求比如需要Android还是iOS、需要什么系统版本来分配设备。分配算法用的是贪心策略优先把测试用例分配给最匹配的设备。任务队列管理。所有待执行的测试用例进入一个队列调度器从队列里取任务分配给空闲设备。队列支持优先级冒烟测试的优先级高于全量回归。资源隔离。每台设备上的测试进程相互隔离一个进程崩溃不影响其他进程。ARTEMIS用容器化技术做隔离每个测试任务跑在独立的容器里。失败重试。测试用例失败后会自动重新排队分配给另一台设备重试。重试次数可配置默认是2次。如果重试都失败才标记为最终失败。实操心得并行执行时设备发热和性能下降是常见问题。我建议在设备之间加散热风扇并且每跑完一批测试就让设备休息几分钟。另外并行度不要设得太高一般每台控制机管理4到6台设备比较合适太多了控制机本身会成为瓶颈。8. 从ARTEMIS架构中能学到什么ARTEMIS的双模式架构给我最大的启发是不要试图用一种方案解决所有问题。移动端自动化测试的场景太复杂了有的场景需要速度有的场景需要智能有的场景需要稳定性。把这些需求拆开用不同的模式分别满足比强行做一个“全能”的方案要务实得多。Direct模式和Agentic模式的划分本质上是在确定性和灵活性之间做权衡。Direct模式牺牲了一部分灵活性换来了速度和稳定性Agentic模式牺牲了一部分速度和稳定性换来了对复杂场景的适应能力。两种模式共享底层能力通过调度层协同工作整体效果比单一模式好得多。这个思路不仅适用于移动端自动化测试也适用于其他LLM落地的场景。比如在客服系统里简单问题用规则引擎快速回答复杂问题转给LLM处理在代码生成里模板化的代码用代码片段库需要推理的部分用LLM。这种“分层处理”的思路是LLM工程化落地的一个通用模式。我在自己的项目里借鉴ARTEMIS的架构搭了一套类似的测试系统。Direct模式的部分用传统的UI测试框架做底座Agentic模式的部分用LLM做决策中间加了一个调度层做模式切换。跑下来的效果比之前纯脚本的方案好了不少测试用例的通过率从70%多提升到了90%以上维护成本也降下来了。当然ARTEMIS也不是银弹。它的Agentic模式在复杂界面上的决策准确率还有提升空间双模式切换的开销在某些场景下也比较明显。但作为一个架构参考它的设计思路是值得学习的。特别是对于那些正在探索LLM在测试领域落地的团队ARTEMIS的双模式架构提供了一个很好的起点。最后分享一个我在实践中总结的小技巧先用Direct模式跑通全流程再逐步引入Agentic模式。不要一上来就全用Agentic那样调试成本太高。先把Direct模式的骨架搭好确保基础流程能跑通然后在那些Direct模式搞不定的环节上有针对性地引入Agentic模式。这样渐进式的落地风险可控效果也更容易验证。