首页 / 资讯中心 / 文章详情

Midscene.js实战:用自然语言驱动UI自动化测试,告别选择器维护

Midscene.js实战:用自然语言驱动UI自动化测试,告别选择器维护 ★ FEATURED ARTICLE
试了一圈AI测试工具最后我留下的那个叫Midscene.js。这东西最早是在一个技术群里看到有人发Demo一句打开登录页输入账号密码点提交然后断言出现欢迎消息脚本就自己跑起来过程全程带截图像有人录了一遍屏。当时第一反应是又一个玩具后来发现它在定位方式、断言逻辑和工作流组织上跟传统UI自动化测试完全不是一个思路。这篇就按我实际部署和使用的经验从零到一讲清楚Midscene.js怎么用、原理是什么、坑在哪里争取让你拿到手5分钟就能跑起第一版AI自动化测试。先说结论它解决的是传统UI测试里最让人头大的选择器维护问题。写自动化测试的人都有过这种体验——CSS类名改一个id重构一次整条用例红线一片写着写着就变成了改脚本比跑脚本快。Midscene.js的思路是不用你写具体的选择器而是用自然语言描述你要对页面做什么由大模型去理解页面结构、匹配目标元素、执行操作并做断言。这意味着脚本的可读性、抗前端改动能力和编写速度都上了一个台阶。1. 为什么UI自动化测试总在改脚本Midscene.js给出了新解法1.1 传统选择器式测试的三个死穴以前写UI自动化不管是基于WebDriver的方案还是基于Playwright的方案核心都是两件事先找到元素再操作元素。找元素靠什么靠id、name、CSS选择器、XPath顶多再包一层数据属性。听起来很标准可实际操作里全是问题。第一个死穴是结构耦合。XPath写//div[classlogin-form]/div[2]/input前端同学稍微调整一个DOM层级这条路径就废了CSS类名是开发随手改的改完你连哪条用例挂了都要排查半天。第二个死穴是动态内容。页面上有异步加载的数据、根据接口返回值变化的文案、随机生成的token这些元素你在写脚本时根本没法用固定选择器去描述。经常是脚本跑到第三个小时唯一在做的就是在网上搜Playwright下拉框选择器怎么写。第三个死穴是断言能力太弱。传统断言要么是等某个元素出现要么是比对纯文本真想让脚本判断页面上有没有出现一个红色错误提示条就得去写复杂的条件逻辑。这三个死穴导致一个结果UI自动化测试的成本被严重低估。用例的编写、维护、还有因为前端一丁点改动带来的精神污染加起来远超收益。所以很多团队做了两三个月UI自动化就放弃了退回手动测试加少量冒烟脚本。1.2 Midscene.js是什么把怎么找换成找什么Midscene.js把这个逻辑彻底调了个方向。它不让脚本关心元素长什么样、在第几个层级而是让脚本描述用户想做什么。比如在登录页的邮箱输入框填入abcexample.com密码框填入a123456然后点击登录按钮等待页面出现欢迎回来——这一段自然语言在传统框架里你可能要写十行二十行代码在Midscene.js里就是一条指令。底层是怎么实现的它会把当前页面的可访问性结构、文本内容、视觉信息等等一股脑打包交给大模型去推理由模型决定邮箱输入框对应页面上的哪个元素再自动完成输入和点击。这个过程中元素的选择不是靠固定的路径而是靠语义理解。前端把那个input的id改了、class重构了都不影响只要页面上仍然有一个邮箱输入框脚本就能找到它。对测试工程来说这意味着脚本从脆弱的DOM操作序列变成了意图文档。测试脚本维护的频率会大幅下降写用例的速度也会明显变快。而且Midscene.js不只支持页面操作还支持自然语言断言、开放性问答、步骤截图留痕后面我会逐个拆。2. 5分钟部署实战三种落地姿势任选很多人看到AI测试第一反应是又要配半天环境。Midscene.js的好处是给出了三种使用方式从零代码到工程化按需选真正的5分钟跑通指的是第一种。2.1 零代码路线浏览器扩展一首歌的时间跑通最省事的方式是直接从应用商店装它的浏览器扩展以Chrome系浏览器为例。装完扩展后你需要准备一个LLM服务商的API Key。Midscene.js底层需要调用大模型来理解页面和执行指令所以这一步绕不开。没有Key去国内合规的大模型服务商平台注册一个通常都有免费额度够你试几十次。装好扩展、配好Key之后打开任意一个网站最好是带表单、带按钮的页面点击扩展图标在弹出框里用自然语言下指令类似把页面上所有商品名称提取出来或者点击右上角的购物车图标。它会自动操作页面执行过程中会高亮正在操作的元素每一步都有截图记录。如果你愿意还可以直接用录音式的语气描述一个完整的用户路径扩展会按顺序执行。这种方式特别适合QA同学、产品经理、甚至不懂代码的运营来做初步验证我见过不少团队先拿它做冒烟回归再决定要不要下沉到CI。2.2 工程化路线Playwright SDK适合当回事做如果要把AI自动化测试纳入日常开发和流水线零代码扩展是不够的得走SDK路线。Midscene.js提供了JavaScript/TypeScript的SDK和Playwright结合得非常紧密。先初始化一个Node项目然后安装两个依赖Playwright本体和midscene的SDK包再加一个测试运行器如果你熟悉Jest或Vitest直接用就行我个人用的是最基础的Jest配置。装完依赖后写一个最小脚本逻辑非常直白启动浏览器、打开页面、把页面交给Midscene的agent对象、然后对agent下自然语言指令。这里我贴一个我实际跑过的最小示例import { chromium } from playwright; import { createAgent } from midscene; const browser await chromium.launch({ headless: true }); const page await browser.newPage(); const agent await createAgent(page, { // 根据你选的模型服务把baseURL和apiKey换成对应的值 baseURL: process.env.MY_LLM_BASE_URL, apiKey: process.env.MY_LLM_API_KEY, }); await agent.execute(打开测试站点 https://example.com/login); await agent.execute(在邮箱输入框输入 testexample.com密码框输入 Test123456然后点击登录按钮); await agent.assert(页面上出现欢迎回来的提示且没有红色错误提示); await browser.close();第一次跑通这个脚本正常情况下不需要5分钟因为你只需要做三件事装依赖、配环境变量、复制粘贴以上代码。跑起来之后你会看到浏览器窗口自动打开、光标自动落到输入框、文字自动敲入、按钮被点击整个过程像有个人在旁边操作。2.3 工作流路线YAML脚本化面向回归和协作SDK适合在测试代码里写逻辑但如果你要的是一份能让业务同事也看懂、能评审、能直接编进回归清单的脚本那就要用YAML工作流模式。这种模式下你把测试步骤写成结构化的YAML文件每一步声明要做的事Midscene的工作流引擎会按顺序执行并且在结束后生成可视化报告。一个简单的示例如下name: 登录流程回归 steps: - action: ai instruction: 打开 https://example.com/login - action: ai instruction: 点击登录按钮 - action: ai instruction: 在邮箱输入框填写 testexample.com密码框填写 Test123456然后点击确认登录 - action: ai_assert condition: 页面上能看到用户头像和个人中心入口且页面标题包含我的账号YAML写出来的好处是脚本即文档。传统自动化测试的代码非技术成员基本没法review而这份YAML业务负责人扫一眼就知道覆盖了哪些步骤。很多团队的手工回归用例文档可以直接翻译成这种工作流文件省掉大量的翻译成本。3. 核心机制拆解AI如何看懂页面并动手如果你只会用不会拆后面遇到问题会非常痛苦。我花点篇幅讲讲Midscene.js底层的工作机制理解它之后写指令的时候就会少很多玄学。3.1 LLM定位元素的真实过程传统框架定位元素靠的是DOM查询Midscene.js靠的是语义映射。当页面加载完成后SDK会把页面的结构化信息提取出来——包括DOM树的语义标签、输入框的占位符、按钮的可见文本、图片的alt文本、可访问性层级等——打包成一个结构化的页面上下文。然后它把这条指令和页面上下文一起发送给大模型由模型推理出用户说的邮箱输入框对应在页面上下文里的哪一个节点。这个过程的关键在于它不是在做纯字符串匹配而是在做意图对齐。你说那个蓝色的提交按钮页面里可能有个class叫btn-primary的按钮文本是提交样式恰好是蓝色模型能从视觉和语义维度综合判断。甚至页面布局改了、按钮挪了位置模型依然可以通过可见文本提交和输入框前的邮箱标签来锁定目标。这就是为什么它比传统选择器抗结构变化。有一个细节值得留意Midscene.js把页面上的文字和输入的交互元素都当成了推理的依据所以页面上出现非标准控件——比如用div模拟的下拉框、自定义渲染的日历组件——它一样可以操作因为模型看到的是这是什么控件、上面写了什么、大概在哪个位置而不是它有没有标准select标签。3.2 多步操作背后的感知-行动循环单条指令好理解但像打开登录页填写表单点击按钮然后等待跳转这种多步流程模型是怎么一步步执行的它的内部其实是一个感知-行动循环先观察当前页面规划下一步动作执行动作输入、点击、滚动再次观察页面状态验证上一步是否生效如果生效就进入下一步如果没生效比如弹出了校验提示、按钮被遮住就根据观察结果修正动作。这个过程类似人操作电脑时的看一眼、点一下、再看一眼。所以它天然适合处理页面上的异步状态。比如点击登录后接口可能有2秒的延迟才会返回结果此时页面会暂时显示loading状态。传统脚本需要手工写等待某个元素出现来兜底而Midscene.js会在循环中自动感知页面变化等到欢迎回来出现时再做断言。当然我不会说完全不用写等待逻辑复杂的场景你还是可以显式加一句等待页面加载完成再继续但大部分常规流程它自己就消化了。3.3 可解释性为什么每一步都要留证AI生成的自动化测试最大的信任危机是黑盒。它执行完说通过了你到底该不该信Midscene.js对这个问题给出的方案是全链路留痕每一步操作都会截取当前页面快照并在截图上标注它选择的元素位置、输入的文本、点击的坐标还会记录每一步模型推理的关键结论。最后生成一份HTML报告滚动下来就是一张张带标注的截图像操作录屏一样清楚。我个人的看法是这份报告的价值甚至不低于测试本身。传统UI自动化挂一条用例你要去翻日志、看截图、猜是哪一步出了问题。Midscene.js生成的是结构化的操作轨迹回归的时候扫一眼报告你脑子里就能还原整个用户路径。团队内部评审、跟开发解释为什么脚本认为这个元素没出现都变得非常简单。4. 完整Demo从登录到下单的AI自动化流程下面放一个我实际写过的完整Demo模拟电商站点从登录到加购再到提交订单的路径。这一节你可以直接当模板抄。4.1 场景设计先把意图写好写AI测试脚本有个小习惯先写情境描述再动手敲代码。因为Agent模式下脚本的可读性直接影响可维护性。我先用中文描述整个用户路径打开首页、登录、去商品列表页、把第一个商品加入购物车、进入购物车、结算下单、断言订单成功页出现。注意这里每一步都是用户语言不是代码语言。实际写的时候我倾向于把动作和断言混排。动作是执行路径断言是路标。如果只描述动作那脚本跑完你并不知道结果到底对不对只写断言又看不到路径。混排才能让报告更有解释力。4.2 核心代码与执行细节完整脚本我精简了一下但核心逻辑都在。跑之前确认你的LLM服务有配额另外建议把浏览器设为非headless模式第一次运行用肉眼盯着方便发现异常import { chromium } from playwright; import { createAgent } from midscene; const BASE https://example.com/shop; describe(AI 自动化测试 Demo登录到下单, () { let browser, page, agent; beforeAll(async () { browser await chromium.launch({ headless: false }); page await browser.newPage(); agent await createAgent(page, { baseURL: process.env.MY_LLM_BASE_URL, apiKey: process.env.MY_LLM_API_KEY, }); }); afterAll(async () { await browser.close(); }); test(用户完成登录到下单的完整路径, async () { // 1. 打开站点并登录 await agent.execute(打开首页如果出现弹窗就关闭它); await agent.execute(点击右上角的登录入口); await agent.execute(在邮箱输入框输入 buyerexample.com在密码输入框输入 Buy123456然后点击登录按钮); await agent.assert(页面右上角出现我的账号入口且没有红色提示条); // 2. 搜索并进入商品详情 await agent.execute(在顶部搜索框输入无线耳机 降噪按下回车); await agent.execute(点击搜索结果列表中的第一个商品卡片); // 3. 加入购物车并去结算 await agent.execute(在当前商品详情页点击加入购物车按钮); await agent.assert(页面上的购物车数量角标变成 1); await agent.execute(点击去购物车按钮等待购物车页面加载完成); // 4. 提交订单 await agent.execute(点击结算按钮); await agent.execute(在收货人输入框填入张三、在手机号输入框填入 13800138000、在详细地址输入框填入北京市朝阳区某街道然后点击提交订单); await agent.assert(页面出现订单提交成功标题订单号不是空); // 5. 输出本轮操作的结构化日志便于后续排查 console.log(agent.logExtract); }, 60000); });代码里几个细节execute用于执行多步操作assert用于做自然语言断言。断言失败时Midscene会返回失败原因并输出当时的页面快照这是我们排查的主要依据。我把整个测试的超时时间设成60秒。AI推理需要时间尤其第一步首次打开页面时模型要理解整个页面结构会比较慢。如果超时了你优先检查模型服务速度和网络而不是急着骂脚本。弹出框、角标数量、异步加载这些场景我都用自然语言做了兜底指令。这也是跟传统脚本最大的体验差异以前判断购物车数量角标变成1要高亮元素、对比text现在就一句话。4.3 运行结果与报告解读跑完一次Demo会在输出目录里生成一份HTML报告。打开报告你能看到每一条execute和assert的具体执行过程模型当时认为页面上的哪个元素是登录入口、点击后页面变成了什么样、什么时候购物车角标变了、哪一步耗时最长。如果某一步鼠标点错位置截图会高亮那个位置配合模型输出的为何选择这个元素十有八九能判断出是指令模糊还是页面本身有歧义。我跑了这个Demo大概五十多次最直观的感受是脚本的稳定性比我预期的好。只要页面结构不出现语义级变化——比如把登录改叫Sign In、把加入购物车隐藏进二级菜单——指令基本不需要改。真正会翻车的反而是那些页面本身状态不确定的场景比如A/B测试导致按钮文案在两种版本间切换。这种不确定性传统脚本也扛不住只能说做AI测试时要接受以语义为准而非以像素为准的哲学。5. 真实踩坑实录问题与排查经验AI测试工具不是银弹实际跑起来会遇到一批新问题。我踩过的坑整理成速查表和经验两条线。5.1 高频问题速查表现象可能原因处理办法首次执行特别慢超过15秒模型推理耗时长或页面结构太大导致需要分析太多元素优先用响应快的模型给测试用例设置更宽的超时缩小操作范围点击了错误的元素指令有歧义页面存在多个相似目标在指令中增加位置、文本、颜色等限定词比如页面右下角的红色提交按钮断言不稳定这次过下次挂页面异步加载时序不同或者显示状态有短暂变化在断言前加一步等待页面稳定或用更宽容的断言表达如购物车数量角标已变更代替等于1跑完一个长流程API费用比预期高每一步都调用了多次模型接口尽量合并操作步骤把多步动作写进一个execute减少实验性指令避免模型反复尝试页面内容复杂时定位不准小控件嵌套深或视觉信息混乱先手动在页面上试一下agent是否能正确理解不行就拆成更细的指令打开页面后输入框始终无法聚焦页面有iframe或shadow DOM阻挡事件先用一条指令滚动到该输入框附近或点击该输入框使其获得焦点再执行输入headless模式下截图全白某些站点对无头浏览器有检测本地调试用有头模式流水线里再切换回headless或改用企业级浏览器环境上面这张表是拿真金白银的API调用和排查时间换来的。最值得留意的还是第一条模型响应速度直接决定整个测试跑得快不快。AI测试脚本虽然有智能但它的推理成本摆在那里不是传统脚本那种毫秒级操作。5.2 三条比官方文档更值钱的实战经验第一条指令要像给新同事布置任务而不是像在写测试用例。给新同事说你打开登录页把邮箱和密码填上点登录看看有没有欢迎横幅他听得懂跟他说断言#login-form div:nth-child(2)的text存不存在他就懵了。Midscene.js吃的是前者。我在实际写脚本时会把我要写的每一句指令都用人能不能照着做来检验一下人做不了的事AI大概率也做不好。第二条混合模式往往最优。AI测试脚本不是非要全包全揽。像我自己的项目现在用的是AI负责核心路径自然语言断言传统选择器负责高频稳定的小操作。比如翻页、滚动这种机械操作传统脚本一个循环就完成交给AI反而慢还费token而页面跳转、语义判断这种需要人看一眼的地方让AI来。这就像做饭AI是主厨菜刀是工具不能要求主厨纯靠手切。第三条必须把报告留档。跑完一轮把HTML报告按日期归档下次跑挂了拿报告对比基本能定位是引入的改动问题还是测试脚本本身的衰退。AI测试有一个隐藏问题它的智能也可能翻车翻车就需要证据链。报告中的截图、模型推理摘要、操作轨迹就是完整的证据链。时间长了你会发现这堆报告本身就是一份极佳的产品演进记录。6. 更多玩法接入CI、混合模式与适用边界如果只是本地跑跑Demo那AI测试的价值还没真正发挥出来。把它放进日常开发循环里价值才最大化。6.1 从本地一键跑通到流水线无人值守我现在的做法是在每次发版前的流水线里加一个阶段先跑传统的接口测试和单元测试再跑Midscene.js的AI回归用例。流水线环境里没有显示器所以用headless模式模型服务用国内稳定可访问的供应商API Key从环境的密钥管理里读取不硬编码在仓库里。为了不让AI测试拖慢整个流水线我做了两个优化。一是把长时间运行的用例拆分成多个独立任务并行跑比如登录流程和个人资料编辑流程同时执行。二是把模型调用配置成测试环境用性价比高的模型正式必发用推理更稳的模型。这样日常开发分支的校验成本可控真正要发版的节点才上满配置。还有一个团队协作层面的好处因为YAML工作流可读性好前端、后端、测试现在能一起评审这条用例到底覆盖了哪些场景。以前UI自动化在团队里是少数人的黑科技现在变成了大家一起维护的回归资产。6.2 适用场景与不要硬蹭的场景讲清楚边界比讲能力更重要。根据我实际用下来的感受Midscene.js非常适合以下场景核心业务路径的冒烟回归登录、注册、下单、支付、跨端的UI一致性检查同一套指令在不同分辨率和浏览器上跑、复杂页面的开放性问答比如这个页面上总共有多少个弹窗这种传统脚本很难写、以及前端频繁改版时的快速回归验证。但它不擅长的地方也很明确对像素级细节的严格断言它不如纯视觉回归工具对极度复杂的交互比如拖拽流程图节点、Canvas里的精细操作模型可能理解不到位执行也容易飘纯接口和数据层的测试完全用不上它那是接口自动化工具的领域。另外如果你的项目处于上线前页面UI还没冻结的阶段比如视觉稿每天都在变那AI测试脚本虽然比传统脚本抗造但依然建议等页面结构稳定再做否则写脚本的时间容易打水漂。我自己的原则是关键路径用AI守住细节场景用传统工具锁死性能和安全交给专业工具。这套组合下来UI自动化的维护成本已经降到过去的三分之一左右而覆盖的场景反而更宽了。Midscene.js的5分钟部署不是噱头它真正改变的是写自动化测试这件事的认知门槛——不再要求你会写选择器、会调试XPath只要求你能把用户操作说清楚。这就够了。最后再分享一个操作小技巧写自然语言指令的时候句子里尽量把名词状态写完整比如点击登录入口比点一下那里可靠提交订单后等待3秒比点击提交然后看结果稳定得多。AI再聪明也只能在你给的上下文里做判断指令的信息密度越高它翻车的概率就越低。这也是我从大量踩坑里得出的最朴素的一条结论。
阅读完成 · 觉得有帮助?
咨询建站