
Appium 架构解析Core、Driver、Client 与 Plugin 四层体系及快速上手路径【免费下载链接】appiumCross-platform automation framework for all kinds of apps, built on top of the W3C WebDriver protocol项目地址: https://gitcode.com/GitHub_Trending/ap/appiumAppium 是一个基于 W3C WebDriver 协议的跨平台 UI 自动化框架其设计目标并非一个程序搞定一切而是通过Appium Core、Drivers、Clients、Plugins四大组成部分的分工协作让同一套自动化 API 覆盖移动、Web、桌面等多类平台。本文以仓库内packages/appium/docs/ja/intro/index.md的Appium in a Nutshell为骨架逐层拆解这四部分的职责与协作关系并结合本仓库源码给出从安装到运行第一条自动化脚本的完整路径帮助你理解为什么 Appium 能以一套 API 驱动一切平台。为什么 Appium 要拆成四个部分Appium 的目标是支持大量不同平台移动、Web、桌面等的 UI 自动化同时还要支持用不同语言JS、Java、Python 等编写自动化代码。把这一切塞进单个程序是一项极其困难甚至不可能完成的任务因此 Appium 将自身拆分为四个可独立演进的部分Appium Core定义核心 API即 W3C WebDriver 协议的实现层Drivers驱动负责建立与具体平台iOS、Android、Windows 等的自动化连接Clients客户端库用具体编程语言封装 Appium 的 APIPlugins插件修改或扩展 Appium 的核心功能。这四部分的分工在本仓库中也有清晰的代码印证packages/appium是服务器核心包packages/base-driver提供了驱动基类与 WebDriver 协议路由packages/base-plugin提供了插件基类而packages/fake-driver、packages/images-plugin等则分别扮演示例驱动和示例插件的角色。开始自动化前需要安装的四样东西要真正开始用 Appium 自动化某个应用你需要依次准备安装 Appium 本身服务器为目标平台安装一个驱动Driver为目标编程语言安装一个客户端库Client可选安装一个或多个插件Plugin。安装 Appium 后官方推荐通过appium driver install与appium plugin install这类 CLI 子命令来管理扩展。例如安装 Android 的 UiAutomator2 驱动与 iOS 的 XCUITest 驱动appium driver install uiautomator2 appium driver install xcuitest关于驱动、插件等扩展的管理与安装细节可进一步阅读本仓库的 扩展管理指南 与 扩展 CLI 参考。准备好这四样东西就可以直接进入 Quickstart 快速入门 跑起第一条脚本。下面我们逐层深入每个部分为什么存在、解决了什么问题。Appium Core以 WebDriver 协议为统一 API为什么选择 W3C WebDriver 规范Appium 并没有发明一套全新的 API而是直接采纳了 W3C 的WebDriver 规范作为自己的自动化接口。这一选择与 Selenium 的历史渊源密不可分Selenium 项目多年深耕浏览器 UI 自动化并与各大浏览器厂商及 W3C 标准组织合作将 WebDriver 接口打造成了官方浏览器自动化标准Appium 顺势沿用该规范让查找元素、与元素交互、加载页面/屏幕等 API 原语几乎可以映射到任何平台。技术上Appium 最早基于比 WebDriver 更早的 JSON Wire Protocol之后随 W3C 规范持续演进如今已完全符合 W3C 规范参见 Appium 工作原理详解 中的说明。两个需要注意的边界即便统一使用 WebDriver 规范仍有两点差异需要使用者知悉部分命令在特定平台可能不支持例如原生移动 App 自动化中无法读取或设置 cookie可能支持超出 WebDriver 命令列表的行为这类命令会以规范合规的扩展形式存在即 Appium 对 WebDriver API 的扩展能力。协议路由的源码印证在本仓库中WebDriver 协议 → 方法名的映射并不是魔法而是集中定义在packages/base-driver/lib/protocol/routes/目录下如w3c.ts、mjsonwp.ts、jsonwp.ts、appium.ts、appium-device.ts等路由文件。驱动作者要判断某个 WebDriver 命令对应的方法名与参数查看该目录即可。同时packages/base-driver/lib/basedriver/driver.ts中导出的BaseDriver类见 driver.ts本质上封装了整个 WebDriver 协议这正是驱动只需继承 BaseDriver 并实现对应方法这一设计的前提。Drivers把 WebDriver 协议映射到具体平台驱动本质上就是继承 BaseDriver 的 Node.js 类严格来说Appium 自己并不负责如何让自动化发生在某个平台上这个责任被完全下放给了一种可插拔的软件模块——Driver。从技术角度看驱动只是一段继承自BaseDriver的 Node.js 代码最简单的一个能装进 Appium 的驱动骨架甚至只有几行import BaseDriver from appium/base-driver class MyNewDriver extends BaseDriver { }把这个空类包装成 Node.js 模块在package.json中声明 Appium 相关字段即可通过appium driver install安装。要让驱动真正干活只需实现与 WebDriver 命令同名的 Node.js 方法。例如实现 WebDriver 的 Navigate To 命令async setUrl(url) { // 在这里实现平台真正的跳转逻辑 }注意setUrl与 Navigate To 看似毫无关联——这套命令 → 方法名的映射正是前面提到的 路由文件 所定义的。仓库中的 fake-driver 就是这套机制的最佳参考实现它继承 BaseDriver 并为commands/目录下的每个命令提供实现。同一命令在不同平台的实现千差万别同一个setUrl在不同驱动中的真实实现可能完全不同浏览器执行 JavaScript 设置window.location.hrefiOS 应用通过 deep link 启动应用Android 应用通过 deep link 启动应用React 应用加载指定路由Unity跳转到指定场景。因此驱动开发真正的挑战不在于处理 WebDriver 协议BaseDriver已经替你封装好了而在于把协议映射到目标平台底层的自动化技术。例如 iOS 的 XCUITest 驱动本质是把 WebDriver 协议翻译成 Apple 的 XCUITest 库调用。多层级架构与代理模式实际驱动往往具有复杂的分层架构。以 iOS 为例XCUITest 框架只能用 Objective-C/Swift 调用且必须在 Xcode 环境下运行因此 XCUITest 驱动被拆成两部分——Node.js 侧挂载进 Appium、处理 WebDriver 命令和 Objective-C 侧真正在设备上调用 XCUITest API即 WebDriverAgent它本身也是一个 WebDriver 实现。于是从你的测试代码到真实点击中间横跨了测试代码 → Appium 客户端 → 网络 → Appium 服务器 → XCUITest 驱动 → WebDriverAgent → Xcode → XCUITest → iOS → macOS 一整条技术栈。正因为两端都说 WebDriver 协议驱动可以采用代理Proxy模式某些命令不需要自己在 Node.js 侧实现而是直接把客户端请求原封不动转发给底层 WebDriver 服务器再把响应原路返回。一个典型例证是 Safari 驱动几乎没有实现任何标准命令全部代理给底层的 SafariDriver 进程。这意味着当你在开源驱动源码里找不到某个命令的实现时很可能是被代理到了别处。仓库中的 jsonwp-proxy 模块 正是这套代理机制的底层实现。官方驱动一览Appium 团队当前官方维护的驱动及其安装命令详见 Appium Drivers 生态列表驱动目标平台模式安装命令UiAutomator2Android / Android TV / Android WearNative、Hybrid、Webappium driver install uiautomator2XCUITestiOS / iPadOS / tvOSNative、Hybrid、Webappium driver install xcuitestEspressoAndroidNativeappium driver install espressoChromium桌面与移动端 Chromium 系浏览器Webappium driver install chromiumGecko桌面与移动端 FirefoxWebappium driver install geckoSafari桌面与移动端 SafariWebappium driver install safariMac2macOS 应用Nativeappium driver install mac2WindowsWindows 应用Nativeappium driver install windows此外还有 Flutter、Roku、Tizen、LG WebOS、NovaWindows 等由社区或第三方组织维护的驱动它们与官方驱动一样通过appium driver install --sourcenpm 包名安装。选择驱动时要注意其维护状态与兼容的 Appium 大版本例如部分驱动已停止维护或仅兼容 Appium 1。Clients让任意语言都能调用 Appium客户端-服务器架构是通用语言支持的根基Appium 本质上是 Node.js 程序但它刻意不采用把 Appium 当库 import 进 Node.js 程序的形态因为那无法满足任意流行语言都能用的目标。幸运的是WebDriver 规范本身是一个基于 HTTP 的协议天然就是为跨网络调用设计的。这带来一个关键架构结论Appium 是一个 HTTP 服务器它必须作为进程运行在某个计算机上并且对运行自动化脚本的机器无论同机还是异地保持网络可达服务器与客户端不必在同一台机器上只要客户端能通过网络向服务器发送 HTTP 请求即可这极大方便了云厂商托管 Appium 服务器、设备和驱动客户端脚本只需指向其安全端点客户端库本质上封装了 HTTP 请求把协议细节藏起来让你以符合该语言习惯的对象和方法写自动化。因此像Find Element这样的命令在协议层面其实就是向 HTTP 端点POST /session/:sessionid/element发送请求:sessionid是服务器在创建会话时生成的唯一会话 ID。这类细节主要对协议实现者有用普通测试编写者应该使用官方客户端库。同一套命令的五种语言写法下面用五种语言演示同一组操作查找元素 → 点击 → 打印文本与页面源码可见语言不同、语义完全一致JavaScriptWebdriverIOconst element await driver.$(//*[textFoo]); await element.click(); console.log(await element.getText()) console.log(await driver.getPageSource())JavaWebElement element driver.findElement(By.Xpath(//*[textFoo])) element.click() System.out.println(element.getText()) System.out.println(driver.getPageSource())Pythonelement driver.find_element(byBy.XPATH, value//*[textFoo]) element.click() print(element.text) print(driver.page_source)Rubyelement driver.find_element :xpath, //*[textFoo] element.click puts element.text puts driver.page_sourceC#AppiumElement element driver.FindElement(MobileBy.AccessibilityId(Views)); element.click(); System.Console.WriteLine(element.Text); System.Console.WriteLine(driver.PageSource);这些脚本底层做的事情完全相同用xpath定位策略调用Find Element→ 用上一步返回的元素 ID 调用Click Element→ 调用Get Element Text并打印 → 调用Get Page Source并打印。选择客户端的两条原则官方维护的客户端包括 Java、Python、Ruby Core、Ruby、.NETC#等安装方式见 Appium Clients 生态列表社区还有 WebdriverIO、Nightwatch.js、RobotFramework、Rust、Swift 等选择。由于每个客户端独立维护选择时应把握两点首选你熟悉/项目使用的语言其次评估该库的功能完整度与维护活跃度——某个特性在 A 客户端有、在 B 客户端未必有虽然所有客户端至少支持标准 W3C 协议和常见 Appium 扩展。另外多数语言的 Appium 客户端构建在对应语言的 Selenium 客户端之上因此查阅完整参考时往往需要同时看 Appium 客户端文档和它依赖的 Selenium 客户端文档。值得一提的是任何符合 W3C WebDriver 规范的客户端一般也能与 Appium 良好集成只是部分 Appium 专有命令可能未实现。Plugins在不对核心动手的前提下改变 Appium 的行为在 Appium 2 中引入的插件系统让任何人都能构建并分享改变 Appium 工作方式的模块而且几乎不受限制。插件与驱动一样通过平行的 Plugin CLI 发布与安装。一个非常直观的例子是仓库中的 images-plugin它为 Appium 增加了基于模板图片查找屏幕区域并与之交互的能力图片查找的核心实现在 finder.ts。也就是说即使 Appium 核心团队永远没有时间为某个想法投入开发社区也能通过插件把该能力带进生态——这正是Appium 是一个平台而非单一工具这一愿景的落地方式。关于插件机制本身可阅读 插件基础包 的源码以及 插件开发指南。从入门到进阶的文档路线本仓库的 intro 系列文档构成了完整的认知闭环建议按此顺序阅读Appium Core 工作原理详解回答统一的 API 是什么、如何映射到平台、如何被多语言调用三大问题并详述 Appium 的庞大愿景Appium Drivers 驱动详解深入接口实现、自动化映射、多层级架构与代理模式Appium Clients 客户端详解理解客户端-服务器架构与选择客户端的标准Appium 项目历史了解 Appium 自 2012 年起从 iOSAuto 到 Appium 3 的演进脉络Quickstart 快速入门装好驱动后按你的语言选择对应的测试向导直接上手。理解了四层架构的分工你在排查问题时就能快速定位故障层——是客户端封装问题、协议路由问题还是驱动对底层自动化技术的映射问题也就能理解为什么一个命令在驱动源码里找不到实现可能被代理了以及为什么同一套 WebDriver 命令能在 iOS、Android、浏览器甚至 TV 上以统一语义运行。【免费下载链接】appiumCross-platform automation framework for all kinds of apps, built on top of the W3C WebDriver protocol项目地址: https://gitcode.com/GitHub_Trending/ap/appium创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考