如果你写过几套UI自动化测试,应该对这种场景不陌生:需求一改、页面DOM一变,几十条用例的CSS选择器一夜之间全部失效;新项目接进来,光梳理可用的元素定位方式就得花一下午。这套“选择器军备竞赛”的活儿,在Midscene.js这里换了打法——它把“找元素”从“写选择器”变成“说人话”,再让多模态大模型去读懂屏幕上到底有什么、该点哪里,用自然语言直接驱动跨平台自动化测试,并在此基础上接入CI流水线做智能调度。这篇文章就围绕Midscene.js的完整实践展开,从核心原理、安装配置、跨平台用例设计,到定时任务里的调度与失败重试,把从零跑通到稳定落地的全过程都过一遍。无论你是刚转行测试开发的新人,还是被选择器维护折磨到没脾气的资深自动化工程师,这套思路都值得参考。
1. 这套工具到底在解决什么问题
1.1 传统UI自动化的三座大山
做UI自动化的朋友应该都有同感,日常维护用例的时间往往比写用例的时间还长。第一座大山是选择器脆弱:前端组件库一升级、布局微调一下,class名或自定义属性一变,XPath和CSS选择器就成片失效。第二座大山是断言太死板:想验证“页面提示错误信息”这类业务逻辑,传统写法需要先定位到具体DOM节点再读取文本,如果文案跨了多个节点,断言逻辑就异常复杂。第三座大山是跨平台重复建设:同一个登录流程,Web端写一套基于浏览器的脚本,Android端写一套原生自动化,iOS端再写一套另一套栈的脚本,三套代码维护三份,成本和心智负担都很大。
传统流派里最主流的解法是页面对象模型加统一选择器规范,比如强制要求开发必须加自定义测试标识,这确实能缓解定位问题,却改变不了“写定位符”这个底层模式。只要页面结构变了,你依然要去改代码、重新发版本、重新跑一轮全量回归。问题不在某个选择器写得不好,而在“用静态规则描述动态界面”这件事本身就有上限。
1.2 AI Agent给了另一种解题思路
Midscene.js走的路线是把界面理解这件事交给多模态大模型。测试人员不再写面向DOM的定位符,而是直接写“点击页面右上角的登录按钮”。模型根据当前页面的视觉快照和DOM结构,自动锁定目标元素并执行操作。这种模式下,页面结构调整对用例的影响被大幅削弱——按钮从左边挪到右边,文案从“登录”改成“立即登录”,只要模型看一眼屏幕仍然知道要点击哪里。
说得直白一点,传统自动化是“告诉电脑元素在哪里”,AI自动化是“告诉电脑你要做什么,让它自己去找在哪”。这是从命令式到意图式的转变。Midscene.js在这个方向上的设计很务实:它不是把整个测试流程都交给模型自由发挥,而是把AI封装成一个个可调用的动作原语(点击、输入、断言、查询),让测试逻辑仍然掌握在工程师手里,模型只负责“理解界面并执行动作”。这样既有AI的灵活性,又保留了自动化测试的可控性。
1.3 三条使用路径怎么选
Midscene.js提供了三条比较典型的接入路径,我按使用场景整理了一张表:
| 使用路径 | 适合谁 | 典型场景 | 上手成本 |
|---|---|---|---|
| 浏览器扩展 | 测试新手、快速验证 | 手工点一遍流程,确认AI能识别页面,导出操作脚本 | 最低,装个插件就行 |
| SDK集成 | 已有自动化框架的团队 | 把AI动作嵌入现有用例,跑CI | 中等,要会Node.js |
| 命令行任务运行 | 调度平台开发者 | 批量执行AI测试任务,对接定时调度 | 中高,需要梳理任务编排 |
我个人的建议是:第一次接触不要急着写代码,先用浏览器扩展在你最头疼的那个业务页面上点一遍。如果AI能顺利找到元素并完成操作,就说明这个方案在你当前的业务场景里可行;如果连最简单的按钮都找不到,那就要回头检查模型选型或页面渲染方式,别硬着头皮上SDK。
2. 核心机制解析:AI是怎么看懂页面的
2.1 多模态模型如何锁定元素
Midscene.js的核心不是某一个API,而是它背后对“页面理解”这件事的处理流程。当模型收到一条“点击登录按钮”的指令时,它实际做的是一次多模态推理。模型拿到的是当前页面的截图和可访问性DOM结构,而不仅仅是HTML源码。视觉信息让模型知道“长什么样的元素是登录按钮”,DOM结构又提供了精确的坐标和节点路径。两者配合,模型返回的不是一句模糊的“应该点左上角”,而是一个带边界框坐标的结构化数据,再由运行时把这个坐标转成真实鼠标事件。
这个设计解决了两个关键问题。第一,画布类、图表类元素在DOM里看是一堆canvas节点,传统选择器无从下手,但AI可以从视觉上一眼看出“这是柱状图”或“这是数据面板”。第二,iframe、Shadow DOM这类复杂结构,只要在视觉上可见,模型一样能理解,不需要像过去那样一层层穿透倒挂的根节点。
2.2 核心动作原语
Midscene.js把AI操作收敛成几个语义明确的原语,这是它比“让AI自由写脚本”靠谱的重要原因。以当前版本为例,常用的动作包括:
ai(instruction):执行一段自然语言指令,比如“在搜索框输入商品名并点击搜索”aiQuery(query):从页面提取数据,返回结构化JSON,比如“提取表格中价格最低的商品”aiTap(target):点击目标元素aiType(target, text):在目标输入框输入文本aiHover(target):悬停到目标上,常用于触发下拉菜单aiAssert(condition):断言页面满足某个条件,比如“页面上出现红色错误提示”
这些原语背后统一走模型推理,但对外暴露的是稳定接口。哪怕模型换了、页面改了,你写的测试代码结构可以保持不变。
2.3 数据提取和断言为什么也交给AI
UI自动化的断言通常最难写,因为业务规则和DOM结构是两套语言。传统做法里,你想断言“当前页面的库存大于0”,你得先找库存文本所在节点,再写正则把数字抠出来,中间还要处理各种空格换行。在Midscene.js里,这条断言可以直接写成“库存数量大于0”,模型自己完成信息定位、数值提取、条件判断三步。数据查询类任务也一样,它在表格式数据、卡片式数据的提取上特别省事,返回结果天然是JSON,可以直接作为接口测试或数据比对的输入。
我把这种设计理解成“把测试从DOM语法中解放出来”。用例读起来接近验收标准里的原话,产品经理写的验收标准甚至可以直接改造成测试用例。从维护角度讲,这种用例的寿命比选择器长得多。
2.4 代价与边界
当然,AI理解不是万能的。模型对页面的理解依赖截图质量,如果页面没有渲染完成、字体加载失败、懒加载内容还没出现,模型的判断可能失准。另外,模型返回坐标偶尔会有偏差,特别是针对面积小、视觉上不明显的元素。所以好的AI测试实践不是完全抛开传统手段,而是把AI选择器和某些兜底策略结合,比如对关键的确定性操作保留传统定位方式兜底,对变化频繁的业务区交给AI。
3. 从零实操:跑通你的第一个AI测试
3.1 前置准备与模型服务配置
开始之前先准备好环境。Midscene.js的运行时是Node.js,建议Node版本在20以上;浏览器侧需要有对应的浏览器实例。模型服务是整套方案里最关键的外部依赖,你需要准备一个支持视觉理解的多模态大模型API服务,以及对应的Key和接口地址。
环境变量一般这样配:
export MIDSCENE_API_KEY=你的模型服务Key export MIDSCENE_BASE_URL=模型服务兼容接口地址 export MIDSCENE_MODEL=视觉模型名称具体变量名以你安装版本的官方文档为准,不同版本的命名略有差异。这里有一个容易踩的坑:很多模型服务需要单独开启“视觉理解”能力,或者使用特定模型标识,配错了会出现“API调用成功但返回内容没有坐标信息”之类的奇怪现象,排查方式下面第六章会专门说。
3.2 路径一:浏览器扩展先手动验证
如果你只是想快速验证AI能不能搞定你的页面,浏览器扩展是最快的路径。安装扩展后打开目标页面,点击扩展图标,会出现一个人机对话面板。在这里输入“点击登录按钮,输入测试账号,然后截图”,AI会按步骤在真实页面里执行,过程中你可以看到每一步的日志和模型返回的坐标。确认流程能跑通,再把这段对话记录导出成测试脚本格式。
这一步的价值在于提前暴露问题:如果模型在你的业务页面上频频找不到元素,说明要么模型选型不对,要么页面截图质量有问题,这些问题在写代码之前发现,成本最低。
3.3 路径二:用SDK写第一条用例
接下来是我最推荐的生产方式:SDK集成。下面是一个和Playwright集成的示例框架:
import { chromium } from 'playwright'; import { Agent } from '@midscene/web'; const browser = await chromium.launch({ headless: false }); const page = await browser.newPage(); const agent = new Agent(page); await page.goto('https://your-stage.example.com/login'); await agent.ai('在用户名输入框输入 tester,密码框输入 abc123'); await agent.aiTap('登录按钮'); await page.waitForTimeout(1500); await agent.aiAssert('页面上出现了"欢迎回来"的提示'); const data = await agent.aiQuery('提取当前页面导航栏里的所有菜单名称'); console.log(data); await browser.close();这段代码干的事情很直白:打开登录页,用自然语言完成输入、点击、断言、提数。你注意看,整个脚本里没有任何一个CSS选择器或XPath,所有和页面结构有关的信息都藏在了自然语言背后。也正因如此,当页面改版时,大概率只需要微调自然语言描述,而不是重写整个脚本。
3.4 路径三:命令行任务批量跑
当你需要把AI测试纳入自动化任务时,命令行方式更顺手。Midscene.js提供任务级别的运行方式,你可以把测试逻辑封装成一个个任务脚本,计划任务或CI工具直接调用。比如:
npx midscene run --task ./tasks/login-flow.js任务脚本内部可以定义多个步骤,每个步骤对应一个AI动作或断言。命令行方式的优势在调度友好:它向外部暴露的是命令和返回码,常见的CI系统都能无缝接入,跑完以后把退出码和日志交给上层平台,整个体系不用为AI测试专门改架构。
3.5 用例编写规范建议
最后分享几条我踩过坑之后总结的用例写法。第一,自然语言描述里要带足上下文,说“点击提交”不如说“点击页面底部的绿色提交按钮”,上下文越具体,模型定位越准。第二,一个动作指令里只放一个核心操作,别把十步操作塞进一句话,拆分执行既便于日志排查,也降低模型出错概率。第三,尽可能不要依赖AI去做精确数值运算,AI擅长理解语义,不擅长精确计算,涉及金额、数量的精确断言还是得结合DOM数据或接口返回去核验。
4. 跨平台自动化测试的落地姿势
4.1 支持哪些平台范围
跨平台主要体现在两个维度:浏览器矩阵和端侧设备。浏览器端,Midscene.js基于常见的浏览器自动化库,天然覆盖多套浏览器内核,同一套AI测试逻辑可以跑在不同渲染内核上。移动端,推荐的做法是与移动端自动化框架配合,由移动框架建立与iOS或Android设备的会话,Midscene.js负责承载AI指令到业务操作的映射。这样Web端和移动端在业务用例层共用同一套自然语言描述,差异被收敛到设备适配层。
4.2 跨平台用例的架构设计
跨平台最容易犯的错是“一套脚本想跑所有端”。实际上Web端和移动端的UI交互差异很大,Web端有悬浮、右键、多标签页,移动端有滑动手势、软键盘、返回键。我的建议是:把用例拆成“业务动作层”和“端上适配层”。业务动作层用自然语言描述业务意图,比如“打开商品详情页并加入购物车”;端上适配层负责把同一个意图翻译成各端能识别的细节指令,比如Web端是“点击购物车图标”,移动端是“点击右下角购物车按钮”。Midscene.js让业务动作层的维护成本大幅下降,但适配层依然需要少量手工代码。
4.3 一个典型的跨平台跑批流程
假设你有Web和Android两个端,回归流程可以这样编排。第一步,在CI里先跑Web端全量AI用例,因为Web环境最容易搭建、运行也最稳定。第二步,把同一批业务用例在Android真机或模拟器上跑,通过移动端自动化网关执行。第三步,对两端结果做一次聚合对比:数据层面可以直接对比查询接口的返回结果,看两端页面展示的商品列表、金额信息是否一致;行为层面则对比核心流程的通过率。实测下来,这种做法对“双端一致性回归”特别有效,过去要人工比对两端差异,现在交给AI测试跑完自动出对比结果。
4.4 跨平台跑批的稳定性策略
跨平台跑批最大的敌人是环境不稳定:移动端设备断连、模拟器启动慢、浏览器崩溃。我的经验是给每条用例设置超时上限和重试次数,比如AI动作单步超时设为10秒,整个用例超时设为3分钟,失败后先重试一次,重试仍失败再截取现场快照供分析。另外,移动端真机建议固定设备池,避免多任务抢占同一设备导致随机失败。
5. 智能调度:把AI测试接入CI/CD流水线
5.1 先想清楚要调度什么
“智能调度”这个词听上去很玄,落到工程层面其实就是三件事:什么时候跑、跑哪些用例、失败之后怎么办。Midscene.js本身是执行引擎,调度逻辑靠CI工具或自研任务编排器来承载。如果你只有一两条AI冒烟用例,用定时任务就够;如果用例规模上了三位数,就需要思考用例分层、执行顺序、失败自愈这些设计了。
一个我比较推荐的分层模型是这样的:代码提交级触发,提交后只跑与被改动模块相关的AI冒烟用例,控制在5分钟内;夜间执行全量AI回归,通常覆盖核心业务主流程;发布前再跑一遍关键路径用例集,作为上线质量门禁。这个模型能避免“什么都跑一跑导致跑一晚上跑不完”的尴尬。
5.2 在CI流水线里配置定时触发
以常见CI平台为例,一个集成了Midscene.js的定时流水线配置大致如下:
name: ai-test on: schedule: - cron: '0 2 * * *' # 每天凌晨2点执行 push: paths: - 'src/**' jobs: run-ai-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - run: npm ci - run: npx midscene run --suite ./suites/core env: MIDSCENE_API_KEY: ${{ secrets.MIDSCENE_API_KEY }}这里有几个细节值得提。任务超时时间要显式设置,AI测试比传统用例更慢,默认超时大概率不够。模型服务Key不要硬编码到仓库里,务必走密钥管理机制。日志要留存完整,AI测试的排查严重依赖日志,每一步模型返回的元数据都要透传到统一日志平台。
5.3 用AI辅助决定跑哪些用例
所谓“智能”不只体现在AI执行测试,也体现在用例选择策略上。如果你的团队有代码改动模块和用例的映射关系,可以在CI里根据代码变更路径智能选择关联用例集。更进一步,可以让模型参与映射:把本次变更的提交说明和改动摘要发给模型,让它判断影响最大的业务流程并推荐对应测试套件。这种AI辅助用例选择在大规模测试集里的价值非常明显,能省下大量的无效回归时间。
实现上不复杂,在CI脚本里加一个“智能推荐”步骤即可。先取出本次变更的差异信息,调用模型服务做一次影响面分析,输出推荐用例集合,再用这个集合去驱动Midscene.js执行。推荐结果可以事后和实际缺陷做对比,持续校正提示词和映射规则。
5.4 失败重试与自愈机制
AI测试的失败原因和传统测试不太一样。传统用例失败多半是断言逻辑问题或被测功能真出Bug;AI测试还有一类失败来自模型理解偏差或截图时机不对。所以失败处理要分层:第一层,超时后自动重跑同一条用例,排除偶发环境问题;第二层,对连续失败超过两次的用例,自动抓取页面截图和DOM快照,调用模型做一次“失败原因初判”,输出是“疑似环境异常”还是“疑似业务Bug”;第三层,被判为“疑似环境异常”的用例自动进入观察清单,第二天以更慢的速度重跑验证。
这个自愈机制跑通以后,测试人员每天维护的重点就从“一条条看失败日志”变成“只处理AI标记为疑似Bug的用例”,效率提升非常明显。值得说明的是,自愈逻辑本身也可以复用模型能力来做初步诊断,但流程控制代码依然是纯逻辑判断,尽量别让模型直接去改CI流程。
5.5 调度报表与质量度量
智能调度跑起来之后,一定要有报表沉淀。每次调度结束,把通过率、失败用例清单、AI推荐用例命中率、平均执行时长汇总成一份趋势报表。我习惯用表格维护,格式类似:
| 指标 | 本周一 | 本周二 | 本周三 | 环比趋势 |
|---|---|---|---|---|
| 用例总数 | 120 | 122 | 121 | 持平 |
| 通过率 | 96.7% | 95.1% | 97.5% | 上升 |
| AI失败初判准确率 | 78% | 83% | 85% | 上升 |
| 平均执行时长 | 42分钟 | 45分钟 | 39分钟 | 下降 |
这些数据既是测试质量的度量,也是模型选型、提示词优化的依据。如果AI失败初判准确率长期偏低,就要考虑升级模型或调整诊断提示词。
6. 踩坑记录与排查手册
6.1 模型返回超时与请求不稳定
AI测试对模型服务的稳定性和延迟都很敏感。实测中,大模型接口的响应时间波动很明显,高峰期单次推理可能从2秒飙到15秒。解决方案有三个方向:一是给模型服务配置足够的并发和超时,二是对AI动作设置合理的单步超时并配合重试,三是尽量用轻量模型处理简单定位任务,只在复杂页面上调用更大的模型。回头来看,这是性价比最高的优化点。
6.2 AI找不到目标元素
这是最让人崩溃的一个现象,页面明明在那,AI偏偏说没看到目标。我遇到的绝大多数情况是页面渲染状态问题:懒加载内容还没出现,AI取得的是缺失内容的页面快照。处理办法是在AI动作前增加显式等待,而不是用固定的定时器。还有一类是元素太小,比如一个不足16像素的关闭按钮,模型视觉上确实难以捕捉,这时候可以退一步用传统定位兜底。我的原则是:常规业务操作交给AI,高危或高频操作的确定性优先,传统选择器该用还得用。
6.3 复杂页面与交互组件
图表、画布、iframe、Shadow DOM,这几个场景最容易翻车。图表类元素AI擅长看到但难以精确定位某个数据点,建议改用查询指令读取图表容器暴露的可访问性标签或图表组件的内部数据,而不是靠视觉去点。iframe和Shadow DOM场景,AI的解析能力明显强于传统选择器,但要注意跨域iframe会有访问限制,必要时得调整浏览器启动参数。总体记住一个原则:让AI处理“语义理解”的部分,让技术手段处理“精确控制”的部分。
6.4 凭据管理与权限风险
模型服务凭据是这套体系里最重要的资产,一旦泄露,轻则被盗刷额度,重则被恶意调用。我见过把Key直接写进测试脚本提交到代码仓库的,这是绝对不能碰的红线。正确做法是:CI平台统一用密钥管理机制存储,本地开发用本地环境变量,公司内部统一由密钥管理系统下发。同时给凭据设置调用白名单和额度上限,这样即使意外泄露也能把损失控制在一定范围内。
6.5 测试数据污染与账号互踢
跨平台跑批的时候,测试账号是最容易忽略的瓶颈。两个并发任务抢同一个账号登录,就会出现“被顶下线”导致的随机失败。我建议按端、按任务创建独立测试账号,或者利用查询指令先从页面提取当前账号信息,避免在脏数据上跑断言。账号数据准备尽量脚本化,通过接口直接造数据,比UI操作效率高一个量级。
7. 一些实际体会与后续扩展
到这里,核心链路已经完整了。我在实际使用这套方案的过程中,最大的体会是:AI测试不是用来消灭传统自动化的,而是用来解决传统自动化解决不好的那一部分问题,比如跨平台一致性、复杂视觉验证、快速原型场景。最舒服的用法是让AI做决策和语义理解,让脚本做执行和数据校验,各发挥各的长处。
后续值得扩展的方向,我目前在看两个。一是把数据提取指令拿到的数据直接喂给接口测试做交叉验证,形成UI层与接口层的闭环质量对比。二是把整个测试过程当成一个持续积累的知识库,每次AI动作的坐标、截图、上下文都沉淀下来,用于训练或微调更懂你们业务页面的私有模型。这件事想象空间不小,等有更多实践成果再单独写一篇分享。