Midscene.js:基于AI视觉的跨平台自动化测试框架解析
2026/7/4 11:01:33 网站建设 项目流程

1. 项目概述:当UI自动化不再依赖“选择器”

如果你做过UI自动化测试,或者尝试过用脚本控制桌面、移动端应用,那你一定对“选择器”(Selector)这个词又爱又恨。爱它,是因为它给了我们一个精准定位界面元素的“钩子”;恨它,是因为这个“钩子”太脆弱了。UI界面的一次重构、一个动态ID、一个跨域的iframe,甚至是一个Canvas绘制的游戏界面,都能让精心编写的自动化脚本瞬间失效。维护这些选择器,成了自动化工程师的“屎山”代码日常。

这就是Midscene.js诞生的背景。它不是一个简单的工具更新,而是一次底层逻辑的颠覆。它的核心主张是:“凡可截图,皆可自动化”。简单来说,Midscene.js 是一个基于视觉驱动的跨平台AI自动化框架。它不再依赖传统的DOM结构或无障碍树(Accessibility Tree)来定位元素,而是通过AI视觉模型“看”屏幕截图,理解界面内容,并执行操作。你告诉它“点击登录按钮”,它就能在截图中找到那个长得像登录按钮的区域并点击,无论这个按钮是HTML的<button>、是Android的TextView、是macOS的NSButton,还是游戏里的一张图片。

这个思路,直接击中了传统自动化最大的痛点——脆弱性跨平台一致性。对于测试工程师、RPA(机器人流程自动化)开发者、甚至是想要自动化一些重复性电脑操作的个人用户来说,Midscene.js 提供了一种全新的、更接近人类操作直觉的解决方案。你不再需要为Web、桌面、移动端分别学习三套不同的自动化API和定位策略,一套基于自然语言的指令,就能通吃所有平台。

2. 核心设计思路:视觉驱动与AI智能体协同

Midscene.js 的架构设计非常巧妙,它并不是简单粗暴地把截图丢给一个大模型然后祈祷它做对。其核心设计可以拆解为两个关键部分:视觉驱动引擎多模型协同的AI智能体策略。理解这个设计,你才能用好它。

2.1 视觉驱动:从“结构寻址”到“视觉寻址”

传统自动化(如Selenium, Appium)是“结构寻址”。它需要深入应用内部,获取UI的源代码或视图树结构,通过ID、XPath、CSS Selector等属性来定位元素。这就像给你一张建筑的结构蓝图,让你按图索骥。

Midscene.js 采用的是“视觉寻址”。它不关心内部结构,只关心最终呈现给用户的像素画面。它通过截取屏幕图像,利用计算机视觉(CV)和多模态大模型(VLMs)来识别图像中的UI元素(按钮、输入框、文本等)及其语义。这就像你指挥一个从未见过这个软件界面的人,只通过看屏幕来操作。

这种方式的优势显而易见:

  1. 无侵入性:无需应用提供任何特殊接口或开启调试模式(对于某些封闭桌面应用尤其有用)。
  2. 跨平台一致性:无论底层是浏览器、Electron、Qt、Flutter还是原生系统UI,在屏幕上都只是一堆像素。Midscene.js 用同一套视觉模型去理解它们。
  3. 突破技术限制:能自动化那些传统方法无法触及的领域,如:
    • 无语义元素:纯图片按钮、Canvas/WebGL绘制的整个界面(如游戏、图表)。
    • 跨域iframe:浏览器安全策略限制,父页面脚本无法直接操作子iframe的DOM,但视觉上它们在同一画面。
    • 封闭原生应用:某些桌面应用不暴露可访问的UI树。

当然,视觉驱动也有其挑战,主要是定位精度执行稳定性。Midscene.js 通过一系列策略来应对,这也是其技术核心所在。

2.2 多模型协同策略:让合适的AI做合适的事

Midscene.js 没有把宝全押在一个模型上,而是设计了一套“多模型组合”策略。这通常包含两类模型协同工作:

  1. 规划模型(Planner):通常是一个强大的通用大语言模型(LLM),如GPT-4o、Claude 3.5 Sonnet或开源的Qwen2.5。它的职责是理解任务。当你给出指令“登录邮箱,然后查看收件箱的第一封邮件”时,规划模型会将这个复杂任务拆解成一系列原子步骤:“1. 定位邮箱输入框并输入账号;2. 定位密码输入框并输入密码;3. 定位登录按钮并点击;4. 等待页面跳转;5. 定位收件箱区域;6. 定位第一封邮件并点击”。

  2. 视觉定位模型(Vision Locator):这是Midscene.js的“眼睛”。它专门负责在截图图像中精准找到规划模型所描述的元素。例如,规划模型说“找到登录按钮”,视觉定位模型就会分析当前屏幕截图,返回一个或多个可能是“登录按钮”的边界框(Bounding Box)坐标。Midscene.js 集成了多个视觉定位模型供选择,如官方推荐的“豆包Seed”(专精视觉定位)、通义千问Qwen-VL系列、Gemini等,也支持接入开源模型。

它们的协同流程通常是这样的:Midscene.js 先让规划模型拆解任务,然后为每一步,获取当前屏幕截图,调用视觉定位模型找到目标,最后通过底层驱动(如Playwright、系统API)在找到的坐标执行点击、输入等操作。执行后,再次截图,进入下一步,形成“感知-决策-执行”的闭环。

实操心得:模型选择的经济账不同的模型在精度、速度和成本上差异巨大。对于追求稳定性和精度的生产环境,豆包Seed或GPT-4V是稳妥之选,但API调用有成本。对于内部测试或对成本敏感的场景,可以尝试Qwen3.7-plus这类开源模型,甚至可以自行微调部署,实现零API成本。Midscene.js支持灵活配置模型策略,你可以为“定位”和“规划”任务分别指定不同的模型,以达到性价比最优。

3. 核心细节解析与实操要点

了解了核心思想,我们来看看Midscene.js具体提供了哪些“武器”,以及在使用中需要注意什么。

3.1 核心API:从原子操作到智能流程

Midscene.js 的API设计兼顾了灵活性与易用性,分为原子API和高级API两层。

原子API让你能进行最精细的控制:

  • aiLocate(description): 核心中的核心。传入一个自然语言描述(如“蓝色的提交按钮”),返回屏幕上匹配元素的坐标信息。你可以用这个坐标做任何事。
  • aiTap(description):aiLocate+ 点击。描述要点击的元素,它帮你找到并点击。
  • aiAssert(description): 视觉断言。描述你期望在屏幕上看到的元素或文本(如“应显示‘登录成功’的提示”),用于验证测试结果。
  • aiFill(description, text): 找到输入框并填入文本。
  • aiScroll(description, direction): 找到可滚动区域(如列表)并向指定方向滚动。

高级/流程API让你描述复杂任务:

  • aiAct(instruction): 这是最常用的高级API。你给它一段复杂的自然语言指令,比如“在购物车页面,将第一个商品的数量增加到2,然后点击结算”,它会内部调用规划模型和视觉模型,自动拆解并执行所有步骤。
  • runSkill(name, params): 运行预定义的“技能”(Skill)。技能是封装好的可复用自动化流程,可以由AI编程Agent生成,也可以手动编写。

3.2 平台集成:如何连接你的应用

Midscene.js 本身是“大脑”和“眼睛”,它需要“手”来执行操作。它通过“桥接器”(Bridge)模式与各种平台的自动化驱动连接:

  1. Web端:无缝集成PlaywrightPuppeteer。你可以直接在现有的Playwright测试脚本中引入Midscene.js,当遇到难以定位的元素时,用aiTap替代page.click(selector)。也可以使用“桥接模式”,让Midscene.js通过WebSocket控制一个已启动的浏览器实例。

    // 示例:在Playwright中使用Midscene const { chromium } = require('playwright'); const { Midscene } = require('midscene'); (async () => { const browser = await chromium.launch(); const page = await browser.newPage(); await page.goto('https://example.com/login'); // 初始化Midscene,连接到当前page const ms = await Midscene.connect({ page }); // 传统方式可能失败:await page.click('button[type="submit"]'); // 如果按钮没有明确selector // 视觉驱动方式: await ms.aiTap('the login button'); // 直接描述即可 await browser.close(); })();
  2. 桌面端(Windows/macOS/Linux):通过底层操作系统提供的自动化接口(如Windows的UI Automation, macOS的AXAPI, Linux的AT-SPI)进行连接。Midscene.js 封装了这些差异,你只需告诉它目标应用的窗口标题或进程名,它就能捕获该窗口的屏幕并进行操作。

    # 示例:YAML配置中指定桌面应用 target: platform: desktop desktop: os: macos appName: "Calculator" # 或使用 bundleId: "com.apple.calculator"
  3. 移动端(Android/iOS):通过Appium或直接使用设备投屏协议。Midscene.js 可以连接到已通过ADB(Android)或WDA(iOS)连接的设备或模拟器,获取屏幕镜像,并反向注入点击、滑动等事件。

    // 连接Android设备 const { Midscene } = require('midscene'); const ms = await Midscene.connect({ platform: 'mobile', mobile: { os: 'android', deviceId: 'emulator-5554' // 通过 `adb devices` 获取 } }); await ms.aiAct('打开设置,进入WLAN页面');

注意事项:环境准备是关键桌面端和移动端的连接比Web端要复杂。确保你的系统已启用辅助功能权限(macOS需要在“安全性与隐私”中授权),移动端设备已开启开发者选项和USB调试。首次搭建环境可能会花些时间,但一旦配通,后续就一劳永逸。官方文档提供了各平台的详细配置指南,务必仔细阅读。

3.3 模型配置与成本控制

这是使用Midscene.js进行生产部署时必须精打细算的部分。你需要在midscene.config.js或环境变量中配置模型。

// midscene.config.js 示例 module.exports = { model: { // 规划模型:负责理解复杂任务 planner: { provider: 'openai', name: 'gpt-4o', apiKey: process.env.OPENAI_API_KEY }, // 视觉定位模型:负责在图中找元素 locator: { provider: 'volcengine', // 字节火山引擎 name: 'seed', apiKey: process.env.VOLC_ENGINE_API_KEY }, // 你也可以使用同一个模型处理两项任务,或使用更经济的组合 // 例如,用Qwen做规划,用Seed做定位,性价比很高 } };

成本控制技巧

  • 缓存策略:Midscene.js支持对视觉定位结果进行缓存。相同的屏幕截图和相同的描述词,第二次会直接使用缓存的结果,大幅减少API调用。对于稳定的UI,开启缓存能节省90%以上的视觉模型调用费用。
  • 降级策略:为非关键任务或回归测试配置成本更低的模型组合。例如,核心冒烟测试用高精度模型,全量回归测试可以用开源自托管模型。
  • 自托管开源模型:如果对数据隐私和成本有极高要求,可以自行部署如Qwen-VL、LLaVA等开源视觉大模型,并通过Midscene.js的本地API端点连接。这需要一定的GPU资源和运维能力,但长期成本最低。

4. 实操过程:构建一个跨平台自动化测试案例

让我们通过一个具体的例子,将上述所有概念串联起来。假设我们要为一个名为“SimpleNote”的跨平台应用(有Web版和桌面版)编写一个自动化测试用例,测试其核心的“创建笔记”功能。

4.1 环境搭建与项目初始化

首先,创建一个新项目并安装依赖。

# 1. 初始化项目 mkdir midscene-simplenote-demo && cd midscene-simplenote-demo npm init -y # 2. 安装 Midscene.js 核心包和 Playwright 桥接器(用于Web) npm install midscene @midscene/bridge-playwright playwright # 3. 安装桌面端桥接器(以macOS为例,其他系统参考文档) npm install @midscene/bridge-desktop-darwin # 4. 创建配置文件 touch midscene.config.js touch test-note-creation.js

编辑midscene.config.js,配置我们的模型(这里使用性价比组合):

// midscene.config.js module.exports = { model: { planner: { provider: 'openai', name: 'gpt-4o-mini', // 使用成本更低的4o-mini做规划 apiKey: process.env.OPENAI_API_KEY }, locator: { provider: 'volcengine', name: 'seed', apiKey: process.env.VOLC_ENGINE_API_KEY } }, cache: { enabled: true, // 开启缓存,节省成本 dir: '.midscene-cache' } };

4.2 编写跨平台测试脚本

我们将编写一个脚本,它能够根据传入的参数,分别测试Web版和桌面版。

// test-note-creation.js const { Midscene } = require('midscene'); async function testCreateNoteOnPlatform(platform, targetConfig) { console.log(`\n=== 开始在 ${platform} 平台测试创建笔记功能 ===`); // 1. 连接到目标平台 const ms = await Midscene.connect(targetConfig); // 2. 使用 aiAct 执行核心测试流程 // 指令写得越清晰、越像人话,成功率越高 const instruction = ` 请执行以下操作: 1. 找到并点击“新建笔记”或“+”按钮。 2. 在出现的笔记编辑区域,找到标题输入框,输入“我的AI自动化测试笔记”。 3. 找到正文输入区域,输入“这是由Midscene.js自动创建的第一条笔记。时间:${new Date().toLocaleString()}”。 4. 找到并点击“保存”或“完成”按钮。 5. 验证是否出现“保存成功”的提示,或者笔记列表中出现了标题为“我的AI自动化测试笔记”的新条目。 `; try { console.log('正在执行自动化流程...'); const result = await ms.aiAct(instruction, { timeout: 120000, // 任务超时时间2分钟 stepDelay: 1000, // 每一步操作后等待1秒,让UI稳定 }); console.log(`✅ ${platform} 平台测试完成!`); console.log('执行报告摘要:', result.summary); // 可以进一步基于result进行断言 if (result.success) { console.log('✅ 核心流程执行成功。'); } else { console.error('❌ 流程执行失败:', result.error); } } catch (error) { console.error(`❌ ${platform} 平台测试失败:`, error); } finally { // 3. 断开连接 await ms.disconnect(); console.log(`已断开与 ${platform} 的连接。`); } } // 配置Web端目标(假设SimpleNote的Web地址) const webConfig = { platform: 'web', web: { bridge: 'playwright', browserType: 'chromium', // 使用Chromium浏览器 launchOptions: { headless: false }, // 非无头模式,方便观察 startUrl: 'https://app.simplenote.com' // 应用登录后的主页 } }; // 配置macOS桌面端目标 const desktopConfig = { platform: 'desktop', desktop: { os: 'macos', appName: 'SimpleNote', // 应用程序名 // 或者使用 bundleId: 'com.automattic.simplenote' } }; // 执行测试 (async () => { // 测试Web端 await testCreateNoteOnPlatform('Web', webConfig); // 测试桌面端(注释掉其中一行来单独测试) // await testCreateNoteOnPlatform('Desktop (macOS)', desktopConfig); })();

4.3 运行与调试

运行脚本前,确保已设置好API密钥的环境变量。

export OPENAI_API_KEY='sk-your-key-here' export VOLC_ENGINE_API_KEY='your-volc-key-here' # 运行测试脚本 node test-note-creation.js

当脚本运行时,你会看到浏览器或桌面应用被自动打开,Midscene.js像一个人一样,观察屏幕,找到按钮,点击,输入文字。所有操作都会以可视化报告的形式保存下来,你可以在midscene-report目录下找到HTML报告,回看每一步的屏幕截图和AI的决策过程,这对于调试失败的用例至关重要。

实操心得:编写高质量指令的“咒语”aiAct的指令质量直接决定成功率。我的经验是:“角色+清晰步骤+预期结果”

  • 角色:开头可以加“你是一个软件测试助手”。
  • 清晰步骤:用数字序号列出步骤,动作(点击、输入)和目标(“保存按钮”)明确。
  • 预期结果:最后加上验证步骤,如“验证是否出现XX提示”。这能帮助AI判断任务是否完成。
  • 避免歧义:如果界面上有多个“确定”按钮,描述为“对话框底部的蓝色确定按钮”。多用特征形容词。

5. 常见问题与排查技巧实录

即使有了强大的AI,自动化过程中依然会遇到各种问题。以下是基于真实项目踩坑总结的排查清单。

5.1 元素定位失败

这是最常见的问题。表现是AI报告“找不到元素”或点击了错误的位置。

排查步骤:

  1. 检查截图:首先查看失败步骤生成的截图。是不是页面还没加载完?是不是出现了意外的弹窗(如Cookie通知)遮挡了目标?AI“看”到的画面和你想象的是否一致?
  2. 审查指令描述:你的描述是否准确、无歧义?例如,“点击按钮”不如“点击那个绿色的、写着‘提交’的按钮”明确。尝试在描述中加入颜色、相对位置(“左上角”、“右下角”)、邻近文本等信息。
  3. 调整模型或参数
    • 如果使用的是低成本模型,尝试切换到更强大的视觉模型(如豆包Seed)。
    • 调整aiLocateaiActconfidenceThreshold(置信度阈值)。默认可能为0.8,降低到0.6可能会找到更多候选,但也可能引入错误。
  4. 使用aiLocate调试:在脚本中临时插入const bbox = await ms.aiLocate(‘你的描述’); console.log(bbox);,查看AI到底找到了什么,以及它的置信度是多少。
  5. 考虑动态内容:如果元素是动态生成的(如列表项),确保你的描述足够唯一。例如,“第一条笔记”可能比“标题为XX的笔记”更稳定,因为后者可能还没被渲染出来。

5.2 流程执行卡住或逻辑错误

AI错误地拆解了任务步骤,或在错误的时间点执行了操作。

排查步骤:

  1. 简化任务:将一个复杂的aiAct拆分成多个更小的aiAct或原子API调用。给AI更简单、更直接的任务。
  2. 增加等待与确认:在关键步骤之间(如点击登录后)手动添加等待(await page.waitForTimeout(2000))或使用aiAssert等待某个标志性元素出现(await ms.aiAssert(‘看到用户仪表盘’)),确保页面状态稳定后再继续。
  3. 审查规划模型的输出:Midscene.js的高级API通常不会直接暴露规划模型的思考过程。但你可以通过开启调试日志或使用底层API来窥探。有时规划模型的理解会出现偏差,这时需要你优化指令的表述。
  4. 分步录制与回放:利用Midscene Playground(如果提供)或自己写脚本,先手动执行一遍正确流程,并记录下每一步的截图和操作。然后让AI学习这个“正确路径”,这比单纯用语言描述更可靠。

5.3 性能与成本问题

自动化运行速度慢,或API调用费用超出预期。

优化策略:

  1. 充分利用缓存:确保在配置中开启缓存。对于UI不变的回归测试,第一次运行后,后续运行成本极低。
  2. 降低截图分辨率:传递给视觉模型的截图不需要4K高清。适当降低分辨率(如1080p)能减少token消耗,提升传输和处理速度,且对定位精度影响很小。
  3. 区域截图(ROI):如果操作只发生在屏幕的某个固定区域(如一个对话框),可以配置只截取该区域进行识别,能显著提升速度和精度。
  4. 模型降级与混合:在CI/CD流水线中,对非关键路径的测试使用成本更低的模型组合。例如,只有主流程用例用GPT-4+Seed,其他用例用Qwen+开源模型。
  5. 批量执行与并发控制:合理安排测试套件的执行顺序,避免频繁的上下文切换。同时,注意控制并发数,避免对被测应用和AI API造成过大压力。

5.4 跨平台差异处理

同一个功能,在Web和桌面端的UI布局、文字提示可能略有不同。

解决方案:

  1. 平台条件判断:在脚本中根据platform变量执行不同的指令分支。
    async function clickSaveButton(ms, platform) { if (platform === 'web') { await ms.aiTap('点击底部工具栏的“保存”图标'); } else if (platform === 'desktop') { // 桌面端可能叫“完成”或使用快捷键图标 await ms.aiTap('点击标题栏右侧的“完成”按钮'); } }
  2. 编写通用指令:寻找跨平台UI的共同点。例如,也许“保存”功能都有一个磁盘形状的图标。指令可以描述为“点击看起来像磁盘的保存图标”。
  3. 抽象公共步骤:将平台无关的步骤(如输入文本)封装成函数,将平台相关的定位部分参数化。

最后,我想分享一点个人体会。Midscene.js这类视觉驱动框架的出现,并不是要完全取代传统的基于选择器的自动化。它们更像是互补的两种工具。对于结构稳定、元素可访问性好的标准Web/移动应用,传统方法依然高效、精确、快速。但对于那些“难啃的骨头”——动态Canvas、老旧桌面软件、无源码的第三方应用——视觉驱动方案是唯一的救星。在实际项目中,我常常采用混合策略:80%的用例用Playwright + Selector快速搞定,剩下20%的“刺头”交给Midscene.js处理。这种务实的结合,才能真正实现自动化覆盖率的全面提升,把测试和开发人员从无尽的选择器维护泥潭中解放出来。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询