框架全解系列 · 第 7 篇(前 6 篇:Selenium / Playwright / Cypress / Espresso / Appium / XCUITest)
事实版本:Maestro CLI 2.10.0(2026-08-31 发布)|开源、Kotlin、15.7k+ stars|本地核心能力免费
开篇:先把 Maestro 在系列里的位置摆正
| # |
框架 |
运行位置 |
测试形态 |
一句话标签 |
| 01 |
Selenium |
浏览器进程外(HTTP 协议) |
命令式多语言 |
Web 自动化鼻祖、WebDriver 协议、跨浏览器 |
| 02 |
Playwright |
浏览器进程外(CDP/协议直连) |
声明式多语言 |
多浏览器上下文、自动等待、网络拦截 |
| 03 |
Cypress |
浏览器进程内 |
声明式 JS |
浏览器内自动等待的前端测试 |
| 04 |
Espresso |
App 同进程 |
命令式 Java/Kotlin |
Android 白盒、与 UI 线程强同步 |
| 05 |
Appium |
进程外(黑盒) |
命令式多语言 |
统一协议、双端一套脚本、驱动插件化 |
| 06 |
XCUITest |
独立进程、白盒 |
命令式 Swift |
iOS 官方、自动同步、原生稳定性 |
| 07 |
Maestro |
进程外(黑盒) |
声明式 YAML |
不写代码、自动等待重试、一套 YAML 跑三端 |
读这篇之前,先记住三个"混血"事实,它们是全文的主线:
-
位置和 Appium 同侧:Maestro 从设备外部"驾驶"UI,不侵入 App 进程、不要求加测试依赖、不编译测试 APK——这点和 Espresso / XCUITest 完全相反。
-
写法和 Cypress 神似:你只描述"我要做什么结果"(点"登录"、看见"欢迎"),不描述"怎么等、怎么重试"。等待、轮询、容错由框架默认接管。
-
载体是 YAML 而不是代码:没有编译器、没有测试框架脚手架,解释执行、改完即跑,手工测试、产品、开发都能写。
一句话本质
| 维度 |
说明 |
| 是什么 |
一个单二进制 CLI(+ 可选的 Studio / Cloud),把人类可读的声明式 YAML,翻译成设备级的真实输入事件 |
| 不是什么 |
它不是又一个 WebDriver 实现,不暴露 DesiredCapabilities,也不需要常驻的 Server 进程和驱动安装 |
| 核心赌注 |
"移动端 UI 天生不稳定,与其要求测试者手写一堆等待和重试,不如让框架把这件事做掉" |
01 Maestro 完整工作原理(结合架构图)
一句话本质:CLI 解释 YAML,通过设备无障碍/输入系统从外部"按下真实拇指"
┌──────────────────────────── Maestro CLI(单个 JVM 二进制)────────────────────────────┐
│ │
│ Flow 解释器 执行编排引擎 Orchestrator 自动同步 Scheduler │
│ ┌──────────┐ ┌──────────────────────┐ ┌──────────────────────────┐ │
│ │ YAML 解析│ ───▶ │ 命令 → 设备动作映射 │ ───▶ │ 每步前:等 UI 空闲/元素 │ │
│ │ 变量/条件│ │ runFlow/JS/tags 调度 │ │ 出现 settle,失败自动重试 │ │
│ └──────────┘ └──────────┬───────────┘ └─────────────┬────────────┘ │
│ │ │ │
│ ┌────────▼─────────┐ ┌────────▼─────────┐ │
│ │ 语义选择器解析 │ │ 视图树轮询/截图 │ │
│ │ text/id/关系定位 │ │ (hierarchy dump) │ │
│ └────────┬─────────┘ └────────┬─────────┘ │
└──────────────────────────────┼────────────────────────────────┼──────────────────────┘
│ 注入真实输入事件 │ 反复抓取视图树
┌────────────────┴───────────────┐
▼ Android ▼ iOS
┌────────────────────┐ ┌──────────────────────────┐
│ adb / input 事件注入 │ │ idb / simctl 驱动模拟器 │
│ UiAutomator 无障碍 │ │(底层复用 XCUITest 能力) │
│ 真机 + 模拟器均支持 │ │ 本地:模拟器;真机走 Cloud │
└────────────────────┘ └──────────────────────────┘
▼ Web
┌────────────────────────────┐
│ 内置 Chromium / 连接浏览器 │
└────────────────────────────┘
图注:上图从左到右是"YAML 进、设备动作出"的数据流;下方按 Android / iOS / Web 三个驱动分叉。编号 ①~⑧ 的运行时序见下表。
Maestro 在移动测试体系里的位置
| 对比项 |
白盒派(Espresso / XCUITest) |
Maestro(黑盒派) |
| 是否进入 App 进程 |
进入(同进程 / 独立测试进程但注入) |
不进入,从设备外部操作系统 UI |
| 是否需要源码/测试依赖 |
需要编译 test APK、加依赖 |
零插桩,App 装着就能测 |
| 能操作系统设置/别的 App |
受限(要授权、跨 App 困难) |
能,它驾驶的是整台设备 |
| 与技术栈耦合 |
Kotlin/Java 或 Swift 强耦合 |
框架无关,Compose/Flutter/RN/原生通吃 |
| 速度 |
极快(进程内直连) |
略慢(每次都要 dump 视图树 + 注入) |
关键设计取向:Maestro 主动拥抱"移动 UI 不稳定"这个前提。官方文档原话是"Maestro embraces the instability of mobile applications and devices and tries to counter it"(拥抱不稳定性并设法抵消)。这与白盒派"我和 App 同步、所以我快且稳"的思路是两条哲学。
一次点击的完整时序(图中编号 ①~⑧)
以 - tapOn: "Login" 为例,从 CLI 启动到点击落地:
| 步骤 |
阶段 |
发生了什么 |
| ① |
读取 Flow |
maestro test login.yaml 启动,Flow 解释器解析 YAML、注入 env 变量、展开 runFlow 子流程 |
| ② |
选择设备 |
自动发现已连接设备:Android 走 adb devices,iOS 走模拟器列表;多个设备时可用 --device 指定 |
| ③ |
建立驱动 |
Android 建立 adb 通道;iOS 通过 idb/simctl 连接模拟器;不需要装任何驱动包到设备 |
| ④ |
dump 视图树 |
执行器抓取当前屏幕的完整层级(含文本、accessibility label、id、坐标、可见性) |
| ⑤ |
语义匹配 |
选择器解析器在视图树里找"Login":先匹配可见文字,再匹配无障碍标签 / id |
| ⑥ |
自动等待 |
若没找到 → 不立即失败,按超时(默认约几秒)反复 dump + 等待 UI settle(等动画、渲染、网络回落) |
| ⑦ |
注入事件 |
命中后,计算元素中心坐标,通过设备输入管道(Android input tap / iOS 对应事件)注入系统级点击,如同真拇指 |
| ⑧ |
重试/确认 |
点击后若下一条断言仍不满足,按内置稳定性策略重试该动作,再进入下一条命令 |
④→⑥ 的"抓树—匹配—等待—再抓树"循环,就是 Maestro 自动等待和抗 flaky 的物理实现;它替代了 Appium 里你手写的 WebDriverWait 和满屏的 sleep。
Android / iOS 底层各靠什么驱动
| 平台 |
底层通道 |
本地支持真机 |
说明 |
| Android |
ADB + 系统 input / UiAutomator 无障碍能力 |
✅ 真机 + 模拟器 |
通过 Android 显示与输入栈操作,与 App 用什么框架无关 |
| iOS |
idb / simctl 驱动模拟器,底层复用 Apple XCUITest 能力 |
⚠️ 本地仅模拟器 |
物理 iPhone 本地不支持,真机测试需走 Maestro Cloud |
| Web |
内置 Chromium / 连接浏览器 |
桌面 + 移动浏览器 |
同一套 YAML,配置区把 appId 换成 url
|
Maestro 和 Appium 到底差在哪(同为黑盒,最容易被问)
| 维度 |
Appium |
Maestro |
| 架构形态 |
常驻 Server(:4723)+ 平台驱动插件 + 多语言 Client |
单 CLI,无 Server、无驱动安装 |
| 测试载体 |
命令式代码(Java/Python/JS…) |
声明式 YAML(边角才用 JS) |
| 等待 |
显式等待,自己写自己维护 |
自动等待,默认接管 |
| flaky 处理 |
自己写重试/稳定性逻辑 |
内置重试 + 稳定性启发式 |
| 谁能写 |
工程/SDET |
手工测试、QA、PM、开发都能写 |
| 平台广度 |
通过驱动覆盖 Android/iOS/Web/Win/macOS/TV |
Android/iOS/Web |
| 扩展方式 |
任意语言,代价是配套脚手架 |
YAML 优先,JS 补边缘 |
一句话:Appium 给你最大自由度,代价是把"等待和稳定"的责任留给你;Maestro 收走自由度,把"等待和稳定"变成默认值。
02 核心语法与定位策略
Flow 文件解剖:两段式,用 --- 分隔
# ===== 配置区(--- 之上)=====
appId: com.example.app # 必填:被测 App 的包名/BundleId
name: 登录冒烟用例 # 可选:Flow 名称
tags: # 可选:标签,用于筛选运行
- smoke
- login
env: # 可选:环境变量
USERNAME: "test@example.com"
PASSWORD: "Test@1234"
---
# ===== 命令区(--- 之下)=====
- launchApp
- tapOn: "用户名"
- inputText: ${USERNAME}
- tapOn: "密码"
- inputText: ${PASSWORD}
- tapOn: "登录"
- assertVisible: "欢迎回来"
| 区块 |
位置 |
作用 |
| 配置区 |
--- 之上 |
声明 appId(或 Web 的 url)、name、tags、env、常量 |
| 命令区 |
--- 之下 |
一串按顺序执行的声明式命令 |
语义选择器:tapOn 的匹配优先级
Maestro 不鼓励坐标和 XPath,优先用语义信息(这也是它抗布局变化的关键):
| 匹配方式 |
写法 |
说明 |
| 可见文字 |
- tapOn: "Login" |
匹配屏幕上显示的文本 |
| 无障碍标签 |
同上 |
文字命不中时匹配 accessibility label / contentDescription |
| id |
- tapOn: { id: "btn_login" } |
取 view 的 resource-id / accessibility identifier |
| 点坐标 |
- tapOn: { point: "50%,80%" } |
百分比或绝对坐标,最后手段 |
| 关系定位 |
- tapOn: { text: "标题", below: "搜索框" } |
above/below/leftOf/rightOf 限定相对位置 |
| 子元素 |
childOf: ... |
在某个容器内找 |
- tapOn:
text: "立即购买"
below: "商品详情"
retryTapIfNoChange: true
设计意图:tapOn: "Email" 命中的是"文字或无障碍标签",因此一次改版只要按钮意思没变,脚本就不会挂;而坐标/XPath 在布局微调时立刻失效。
断言与自动等待
| 命令 |
作用 |
是否自动等待 |
assertVisible: "Welcome" |
断言某元素可见 |
✅ 等它出现 |
assertNotVisible: "Loading" |
断言某元素消失 |
✅ 等它消失 |
assertTrue: ... |
配合 JS 表达式做复杂断言 |
— |
- assertVisible: "订单提交成功"
- assertNotVisible: "加载中"
常用命令速查表
| 类别 |
命令 |
典型用途 |
| App 生命周期 |
launchApp / clearState / stopApp / clearKeychain
|
启动、清数据给"刚安装"状态 |
| 交互 |
tapOn / doubleTapOn / longPressOn / swipe / scroll
|
点击、长按、滑动 |
| 输入 |
inputText / eraseText / hideKeyboard
|
填表单、收起键盘 |
| 断言 |
assertVisible / assertNotVisible / assertTrue
|
校验结果 |
| 列表 |
scrollUntilVisible |
滚到目标元素出现 |
| 系统 |
toggleAirplaneMode / toggleWifi / pressKey
|
系统级操作 |
| 流程 |
runFlow / runScript / evalScript
|
子流程复用、JS 兜底 |
| 条件 |
runFlow: { when: { visible: ... }, commands: [...] } |
按屏幕状态分支 |
| 调试 |
screenshot / copyTextFromClipboard / extendTimeout
|
截图、取剪贴板 |
| 网络 |
openLink |
拉起深链/URL |
条件、循环、子流程、参数
# 条件分支:权限弹窗出现才点
- runFlow:
when:
visible: "允许"
commands:
- tapOn: "允许"
# 循环输入多组数据(配合 env/参数)
- runFlow:
when:
platform: Android
commands:
- tapOn: "仅在安卓点的元素"
子流程复用(runFlow 引用文件):
- runFlow: login.yaml
- runFlow:
file: add_to_cart.yaml
env:
PRODUCT: "矿泉水"
命令行注入参数(双端不同 appId 的常用做法):
maestro test -e APP_ID=com.example.android flow.yaml
maestro test --env APP_ID=com.example.ios flow.yaml
appId: ${APP_ID}
---
- launchApp
JS 兜底:YAML 不够用时的逃生口
| 手段 |
用途 |
evalScript |
执行 JS 表达式,把结果存进变量 |
runScript |
跑一个 .js 文件,处理复杂逻辑 |
- evalScript: { script: "output.dynamicText = '总价 ' + (2 * 3) + ' 元'" }
- assertVisible: "${output.dynamicText}"
经验:90% 的移动端场景 YAML 足够;只有复杂计算、动态字符串、特殊数据构造才请 JS 出场。这和 Appium"一切皆代码"形成鲜明对比。
03 完整实战:YAML 走通"登录 → 浏览商品 → 加购 → 下单断言"
Step 1:工程准备(一次性)
| 项 |
要求 |
| 设备 |
Android 模拟器/真机打开 USB 调试,或 iOS 模拟器启动 |
| 安装 |
App 已安装到设备(Maestro 默认不帮你装,可用 CI 先 adb install) |
| 目录 |
建议 flows/ 下按功能拆文件:login.yaml、checkout.yaml、smoke.yaml
|
Step 2:主流程 + 可复用子流程
flows/login.yaml(登录子流程,带参数):
appId: ${APP_ID}
---
- tapOn: "用户名"
- inputText: ${USER}
- tapOn: "密码"
- inputText: ${PASS}
- tapOn: "登录"
- assertVisible: "首页"
flows/smoke_order.yaml(主流程:组合 + 业务动作):
appId: ${APP_ID}
name: 下单冒烟全链路
tags:
- smoke
env:
USER: "test@example.com"
PASS: "Test@1234"
---
- launchApp:
clearState: true # 干净起步,避免缓存导致 flaky
- runFlow: # 复用登录
file: login.yaml
env:
APP_ID: ${APP_ID}
USER: ${USER}
PASS: ${PASS}
- tapOn: "搜索"
- inputText: "矿泉水"
- pressKey: Enter
- scrollUntilVisible: # 滚到目标商品
element: "天然矿泉水 550ml"
direction: DOWN
- tapOn: "天然矿泉水 550ml"
- assertVisible: "商品详情"
- tapOn: "加入购物车"
- runFlow: # 可能的加购弹窗,条件点掉
when:
visible: "继续购物"
commands:
- tapOn: "去结算"
- tapOn: "购物车"
- tapOn: "去结算"
- assertVisible: "确认订单"
- tapOn: "提交订单"
- assertVisible: "订单提交成功"
- screenshot: order_success
运行:
maestro test --format junit -e APP_ID=com.shop.android flows/smoke_order.yaml
场景延伸 1:跨 App / 系统设置(Maestro 的强项)
白盒框架最头疼的"操作设备本身",在 Maestro 里就是普通命令:
- toggleAirplaneMode
- toggleWifi
- tapOn: "飞行模式" # 直接操作系统设置页
- openLink: "shop://product/123" # 深链拉起
| 能力 |
说明 |
| 操作系统设置 |
改 WiFi、飞行模式、亮度,等同真人操作 |
| 读/处理通知 |
可在通知层面操作(真机/模拟器) |
| 跨 App |
可拉起别的 App 再回来,适合分享/支付/地图跳转 |
场景延伸 2:WebView 混合页与 Web
| 场景 |
配置 |
说明 |
| App 内 WebView |
无需切上下文 |
Maestro 直接按渲染出的文字操作,不必像 Appium 那样 switch context
|
| 纯网页 |
url: https://example.com |
同一套 YAML 语法 |
url: https://example.com
---
- launchApp
- tapOn: "More information..."
- assertVisible: "Further Reading"
场景延伸 3:复杂列表与滚动
- scrollUntilVisible:
element: "已到底部"
direction: DOWN
timeout: 20000
visibility: 90% # 元素可见比例达到才算命中
场景延伸 4:CI 集成(GitHub Actions 示例)
name: Maestro E2E
on: [push]
jobs:
android-e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install & run
uses: mobile-dev-inc/action-maestro-cloud@v1
with:
api-key: ${{ secrets.MAESTRO_CLOUD_API_KEY }}
app-file: app/build/outputs/apk/debug/app-debug.apk
flow-file: flows
| 本地 CI 方式 |
做法 |
| 自建模拟器 |
CI 机器起 Android 模拟器后 maestro test flows/
|
| Maestro Cloud |
上传 APK + flows,云端多机并行,回传报告 |
AI 时代的玩法:让 AI 写并运行 Flow
Maestro CLI 内置了一个 MCP Server,AI 编程助手可以直接操作真实设备:
claude mcp add maestro -- maestro mcp
| 提供的 9 类工具(节选) |
用途 |
list_devices |
列出并选择目标设备 |
inspect_screen |
读取当前视图层级 |
run |
执行内联 YAML 或整个 flow 目录 |
take_screenshot |
截图(便于贴 PR) |
cheat_sheet |
查询 Maestro 语法 |
open_maestro_viewer |
镜像设备屏幕 |
run_on_cloud / get_cloud_run_status
|
提交云端并查状态 |
支持 Claude Code、Cursor、Copilot、Gemini 等。典型用法:你说"登录、把巴黎加入收藏、重启后确认还在",AI 写 Flow、真机执行、选择器失效时自己 inspect 后修正。Maestro Studio 内也有 AI 辅助(MaestroGPT)。
04 环境搭建与版本演进
环境清单(本地最容易翻车的几样)
| 项 |
Android |
iOS |
| 前置工具 |
平台工具 / adb,设备开 USB 调试 |
Xcode + 命令行工具、模拟器 |
| Maestro 本体 |
一个 CLI,无需驱动/SDK 配置 |
同一个 CLI |
| 本地真机 |
✅ 支持 |
❌ 仅模拟器,真机走 Cloud |
| 系统要求 |
macOS/Linux/Windows 均可 |
仅 macOS |
CLI 安装
# macOS / Linux
curl -Ls "https://get.maestro.mobile.dev" | bash
# 升级
maestro upgrade
| 检查项 |
命令 |
| 版本 |
maestro --version |
| 设备连通 |
maestro devices |
| 试运行 |
maestro test flows/smoke_order.yaml |
Studio / Viewer / Cloud 三件套
| 工具 |
形态 |
作用 |
| Maestro Studio |
免费桌面 IDE(mac/Win/Linux) |
可视化构建、元素检查器、点击生成命令、MaestroGPT |
| Maestro Viewer |
设备镜像 |
实时镜像当前设备屏幕,便于观察与调试 |
| Maestro Cloud |
云端服务 |
多设备并行、真机 iOS、企业级报告、CI 集成 |
版本演进与商业模式
| 维度 |
现状 |
| 开源 |
核心框架开源免费(Kotlin),本地无限跑 |
| 维护方 |
mobile.dev(公司化运营,非个人项目,迭代活跃) |
| 当前版本 |
CLI 2.10.0(2026-08-31) |
| Cloud 定价(参考) |
移动端约 $250/设备/月,Web 约 $125/浏览器/月;企业定制(SSO/托管) |
| 真实收益案例 |
Wahed 用例编写从 3–4 小时降到 10–15 分钟;Eneco 回归从 16 小时降到 1 小时内;Komoot 两周建 100+ 用例 |
数据来自 Maestro 官方 benchmark / insights 页面,引用时建议标注"官方口径"。
05 稳定性治理:自动抗 flaky 的能力边界
自动等待是 Maestro 的招牌,但它不是万能。这一章讲清楚边界,避免"以为写了 YAML 就不会 flaky"。
1. 自动同步的边界
| 它能自动搞定 |
它搞不定 / 需要你处理 |
| 等元素出现、等 UI settle |
业务语义错误(文案对但意思错) |
| 等渲染、动画、网络回落 |
极快闪过的瞬时元素 |
| 默认重试动作 |
依赖外部第三方 App 状态的步骤 |
| WebView 直接按文字操作 |
Canvas/自绘 UI 里没有无障碍信息的元素 |
2. 语义定位 vs XPath/坐标
| 定位方式 |
抗改版 |
建议 |
| 文字 / 无障碍标签 |
强 |
首选 |
| id |
强 |
推动开发加稳定 id |
| 关系定位 |
中 |
文字重复时用 |
| 坐标 / XPath |
弱 |
最后手段,最易 flaky |
3. 重试与超时配置
- tapOn:
text: "提交"
retryTapIfNoChange: true # 点击后界面没变则重试
timeout: 10000
- extendTimeout: 30000 # 单步延长超时
| 手段 |
场景 |
retryTapIfNoChange |
点击偶发不响应 |
timeout |
某元素加载偏慢 |
extendTimeout |
大文件/长流程 |
4. 用 clearState 做隔离
- launchApp:
clearState: true # 等同 adb shell pm clear,给"首次安装"状态
| 作用 |
说明 |
| 消除缓存 |
Android App 常缓存数据导致 flaky |
| 可重复 |
保证每次起点一致,便于并行 |
5. iOS 物理机限制(必须提前知道)
| 目标 |
本地 |
备选 |
| iOS 模拟器 |
✅ |
— |
| iOS 真机 |
❌ |
Maestro Cloud 或第三方真机云 |
如果团队强依赖"本地插真机调试 iOS",这条限制要在选型时就摆上桌。
6. 常见坑速查
| 坑 |
现象 |
处理 |
| 无障碍信息缺失 |
自绘/游戏 UI 找不到元素 |
推动加 accessibility label,或退坐标 |
| 文字重复 |
tapOn 命中多个 |
加 id 或关系定位缩小范围 |
| 键盘遮挡 |
输入后点不到按钮 |
hideKeyboard 后再点 |
| 启动动画/弹窗 |
首屏脚本偶发失败 |
用 when 条件处理引导/权限弹窗 |
| 国产机保活 (真机) |
后台执行中断 |
保持设备唤醒、关闭省电策略(CI 真机场景) |
| WebView 异步 |
内容晚到 |
语义断言本身会等,必要时加 timeout |
06 优势与劣势
优势
| 优势 |
说明 |
| 上手极快 |
单二进制、零驱动、5–6 行 YAML 出第一条用例,学习约以天计 |
| 谁都能写 |
手工 QA、PM 可直接维护,降低对 SDET 的依赖 |
| 默认抗 flaky |
自动等待 + 自动重试,少写大量样板代码 |
| 一套 YAML 三端 |
Android/iOS/Web 同语法,混合 App(RN/Flutter)尤其舒服 |
| 零插桩 |
不改 App、不加依赖、不编译测试包 |
| 驾驶整台设备 |
系统设置、通知、跨 App 都是常规操作 |
| AI 原生 |
内置 MCP,可让 AI 直接写并执行用例 |
| 免费核心 |
本地无限跑,小团队零成本起步 |
劣势
| 劣势 |
说明 |
| iOS 真机本地不支持 |
必须 Cloud,强本地真机团队受限 |
| 表达能力有上限 |
超复杂逻辑要靠 JS,且仍不如全语言灵活 |
| 黑盒速度略慢 |
每步 dump 视图树,不及白盒进程内直连快 |
| 平台广度不及 Appium |
不覆盖 Windows/macOS/TV 等 |
| 依赖语义/无障碍 |
自绘 UI、无 label 的元素定位困难 |
| 云能力付费 |
规模化并行/真机 iOS 需订阅 Cloud |
| 调试生态 |
不如 Appium/XCUITest 与 IDE 深度集成成熟 |
07 选型建议:什么项目该用 Maestro
决策表
| 项目特征 |
推荐 |
理由 |
| 小团队、追求快速铺开移动端 E2E |
✅ Maestro |
上手快、零配置、默认稳定 |
| 手工测试/PM 也要维护用例 |
✅ Maestro |
YAML 无编程门槛 |
| RN / Flutter / Compose 跨端,想一套脚本 |
✅ Maestro |
框架无关、一套 YAML |
| 经常测跨 App、系统设置、通知 |
✅ Maestro |
设备级驾驶是强项 |
| 想用 AI 自动写跑用例 |
✅ Maestro |
内置 MCP |
| Android 单 App 深度高频回归 |
➡ Espresso |
同进程更快、白盒更强 |
| iOS 本地插真机为主 |
➡ XCUITest 或 Appium |
Maestro 真机需 Cloud |
| 已有 Selenium/Appium 多语言体系与 POM |
➡ Appium |
统一语言与模型的组织价值更大 |
| 需要覆盖 Win/macOS/TV |
➡ Appium |
Maestro 不覆盖 |
| React Native 灰盒同步 |
➡ Detox(备选) |
状态同步更贴合 RN |
系列 7 框架总选型表
| # |
框架 |
平台 |
运行位置 |
脚本形态 |
上手成本 |
自动等待 |
iOS 真机 |
跨 App/系统 |
适合谁 |
| 01 |
Selenium |
Web |
进程外(HTTP/WebDriver) |
多语言 |
中 |
自己写 |
— |
❌ |
SDET/测试团队 |
| 02 |
Playwright |
Web |
进程外(CDP 直连) |
多语言 |
低 |
✅ |
— |
❌ |
前端/SDET |
| 03 |
Cypress |
Web |
浏览器进程内 |
JS |
低 |
✅ |
— |
❌ |
前端 |
| 04 |
Espresso |
Android |
App 进程内 |
Java/Kotlin |
中 |
同步 |
— |
弱 |
Android 开发 |
| 05 |
Appium |
全平台 |
进程外黑盒 |
多语言 |
高 |
自己写 |
✅ |
✅ |
SDET |
| 06 |
XCUITest |
iOS |
独立进程白盒 |
Swift |
中 |
✅ |
✅ |
弱 |
iOS 开发 |
| 07 |
Maestro |
Android/iOS/Web |
进程外黑盒 |
YAML(+JS) |
极低 |
✅+ 重试 |
❌(需 Cloud) |
✅ |
全员/QA/PM |
表外补充:Detox 专做 React Native(iOS/Android、灰盒、JS/TS),状态同步更贴合 RN,RN 重度团队可单独评估,不属于本系列 7 篇主线。
一句话结论
| 你的处境 |
选择 |
| 想要"少折腾、快速见效、人人能写、还能让 AI 帮忙"的移动端 E2E |
Maestro |
| 要最大平台/语言自由度和企业级统一体系 |
Appium |
| 单端深度回归、追求极限速度 |
Espresso(安卓)/ XCUITest(iOS) |
Maestro 的本质不是"更简单的 Appium",而是把"等待、重试、同步"这些本该由框架负责的事从测试者手里收回去——你只负责描述意图,剩下的交给它。 在 AI 写测试成为常态的 2026 年,这种"声明意图 + 机器执行"的形态,反而比"人写命令式代码"更顺。
参考资料
↙↙↙阅读原文可查看相关链接,并与作者交流