Appium源码深度解析:从驱动到架构

Appium 源码概览

Appium 是一个开源的移动自动化测试框架,支持跨平台(iOS、Android)和多种编程语言(Java、Python 等)。其源码托管在 GitHub 上,主要由 JavaScript 和 Node.js 实现,核心逻辑围绕客户端-服务器架构设计。

  • GitHub 仓库地址:https://github.com/appium/appium
  • 核心模块:包含驱动管理(如 XCUITest、UIAutomator2)、协议适配(WebDriver)、设备交互逻辑等。

源码结构与关键模块

驱动层(Drivers)

位于 /packages 目录下,每个子目录对应不同平台的驱动实现:

  • appium-xcuitest-driver:iOS 平台的 XCUITest 驱动。
  • appium-uiautomator2-driver:Android 平台的 UIAutomator2 驱动。
  • appium-espresso-driver:Android 的 Espresso 驱动。

驱动模块负责与设备原生测试框架交互,封装了自动化操作(如点击、滑动)的底层实现。

服务器核心(Appium Server)

位于 /packages/appium 目录,包含以下核心功能:

  • 路由管理:处理客户端请求(如创建会话、执行命令)。
  • 插件系统:支持扩展功能(如图像识别、OCR)。
  • 日志与配置:日志记录和全局配置管理。
// 示例:服务器启动逻辑(简化)
async function startServer () {const appium = new AppiumServer();await appium.listen(config.port);
}
客户端协议(WebDriver)

Appium 扩展了 WebDriver 协议,支持移动端特有操作(如安装应用、模拟手势)。协议定义位于 /packages/base-driver 中:

  • protocols/webdriver.json:标准 WebDriver 命令。
  • protocols/appium.json:Appium 扩展命令。

编译与调试

环境准备
  1. 安装 Node.js(v16+)和 npm。
  2. 克隆仓库:
    git clone https://github.com/appium/appium.git
    cd appium
    npm install
    
运行本地服务器

通过以下命令启动开发模式:

npm run build
npm run dev

调试时可通过 --debug 参数输出详细日志:

appium --log-level debug

扩展与二次开发

自定义驱动
  1. 继承 BaseDriver 类,实现平台特有方法。
  2. 注册驱动到 Appium 的 driver-list.json 中。
// 示例:简单驱动框架
class CustomDriver extends BaseDriver {async createSession (caps) {// 实现会话创建逻辑}
}
修改协议

编辑 appium.json 文件后需重新编译:

npm run compile

基于Rust和Appium的自动化测试 

以下是基于Rust和Appium的自动化测试实践示例,涵盖常见移动端测试场景,按功能模块分类整理:

链接准备

手机可以用各个品牌得手机助手进行链接,保证手机usb链接成功,并且运行操作手机,建议把手机屏保去掉,不允许屏保。

环境配置与基础设置

use thirtyfour::prelude::*;
use tokio;#[tokio::main]
async fn main() -> WebDriverResult<()> {let caps = DesiredCapabilities::android().device_name("emulator-5554").automation_name("UiAutomator2").app("/path/to/app.apk").no_reset(true);let driver = WebDriver::new("http://localhost:4723/wd/hub", &caps).await?;driver.quit().await?;Ok(())
}

确保Appium服务器已启动(默认端口4723),需匹配对应的Android/iOS capabilities

如果碰到端口冲突,可以修改端口编号。

元素定位策略

XPath定位示例:

let search_field = driver.find_element(By::XPath("//android.widget.EditText[@resource-id='com.example:id/search']")).await?;

ID定位示例:

let login_btn = driver.find_element(By::Id("com.example:id/login_button")).await?;

CSS定位(iOS):

let submit_btn = driver.find_element(By::Css("XCUIElementTypeButton[name='Submit']")).await?;

常见交互操作

文本输入:

search_field.send_keys("Rust自动化").await?;

点击操作:

login_btn.click().await?;

滑动操作:

driver.touch_action().press(500, 1500).move_to(500, 500).release().perform().await?;

高级场景处理

等待策略:

use thirtyfour::components::ElementWaiter;
let elem = driver.query(By::Id("dynamic_element")).wait().await?;

处理混合应用:

driver.switch_to_context(Context::Native).await?;
driver.switch_to_context(Context::WebView("WEBVIEW_com.example")).await?;

多窗口切换:

for handle in driver.windows().await? {driver.switch_to_window(handle).await?;if driver.title().await?.contains("Target") {break;}
}

断言与验证

文本验证:

assert_eq!(welcome_text.text().await?, "Welcome, User");

元素存在验证:

assert!(driver.find_element(By::Id("success_message")).await.is_ok());

截图保存:

driver.screenshot_to_file("/path/to/screenshot.png").await?;

性能测试示例

获取启动时间:

let metrics = driver.execute_script("mobile: getPerformanceData", json!({"packageName": "com.example.app","dataType": "activity_resume_time"
})).await?;

持续集成集成

GitHub Actions配置片段:

- name: Run Appium testsrun: |cargo install appium-doctorappium-doctor --androidcargo test --features android

完整项目应包含:

  1. 合理的Page Object模式目录结构
  2. 配置文件管理不同环境capabilities
  3. 日志系统和错误处理机制
  4. 测试数据管理模块

建议参考以下开源项目进行深入:

  • thirtyfour crate文档
  • Appium官方Java客户端实现
  • 社区维护的Rust Appium示例库

Go语言环境(建议1.16+版本)和Appium服务器(2.0+)

安装与配置

确保已安装Go语言环境(建议1.16+版本)和Appium服务器(2.0+)。安装必要的Go依赖库:

go get github.com/tebeka/selenium
go get github.com/fsnotify/fsnotify

配置Appium desired capabilities示例:

caps := selenium.Capabilities{"platformName":    "Android","deviceName":      "emulator-5554","app":             "/path/to/app.apk","automationName":  "UiAutomator2",
}

基础操作示例

启动会话并打开应用:

wd, err := selenium.NewRemote(caps, "http://localhost:4723/wd/hub")
defer wd.Quit()
elem, _ := wd.FindElement(selenium.ByID, "com.example:id/button")
elem.Click()

文本输入与清除:

input, _ := wd.FindElement(selenium.ByName, "username")
input.SendKeys("testuser")
input.Clear()

元素定位策略

XPath定位:

wd.FindElement(selenium.ByXPATH, "//android.widget.Button[@text='Login']")

UIAutomator定位:

wd.FindElement(selenium.ByAndroidUIAutomator, `new UiSelector().className("android.widget.EditText")`)

Accessibility ID定位:

wd.FindElement(selenium.ByAccessibilityID, "login_button")

手势操作示例

滑动操作:

wd.Swipe(startX, startY, endX, endY, durationMs)

长按元素:

actions := selenium.NewTouchActions(wd)
actions.LongPress(elem)
actions.Perform()

混合应用处理

切换WebView上下文:

contexts, _ := wd.Contexts()
wd.SwitchContext(contexts[len(contexts)-1])

查找网页元素:

wd.FindElement(selenium.ByCSSSelector, ".login-form")

高级交互示例

模拟物理按键:

wd.KeyEvent(android.KeyCodeHOME)

处理通知栏:

wd.OpenNotifications()

文件上传操作:

wd.PushFile("/sdcard/test.txt", []byte("file content"))

测试框架集成

与testing包集成:

func TestLogin(t *testing.T) {wd.FindElement(selenium.ByID, "login").Click()if _, err := wd.FindElement(selenium.ByID, "welcome"); err != nil {t.Fatal("Login failed")}
}

并行测试配置:

cap1 := createCapabilities("Android", "emulator-5554")
cap2 := createCapabilities("Android", "emulator-5556")
go runTest(cap1)
go runTest(cap2)

性能监控

获取CPU使用率:

wd.ExecuteScript("mobile: shell", map[string]interface{}{"command": "top -n 1",
})

内存数据采集:

wd.ExecuteScript("mobile: shell", map[string]interface{}{"command": "dumpsys meminfo",
})

异常处理

元素等待策略:

wd.SetImplicitWaitTimeout(10 * time.Second)

自定义等待条件:

selenium.Wait(wd, func(wd selenium.WebDriver) (bool, error) {return wd.FindElement(selenium.ByID, "progress").IsDisplayed()
})

截图处理:

wd.TakeScreenshot().WriteToFile("/path/screen.png")

特殊场景处理

横竖屏切换:

wd.Orientation(selenium.Landscape)

模拟网络条件:

wd.ExecuteScript("mobile: setNetworkConditions", map[string]interface{}{"offline": false,"latency": 500,
})

日期选择器操作:

wd.ExecuteScript("mobile: setDate", map[string]interface{}{"element": elem,"year":    2023,"month":   8,
})

注:以上为精选核心示例,完整需结合具体测试场景扩展实现,建议参考Appium官方文档补充各功能的详细参数配置。实际应用时需根据被测应用的UI层次结构调整定位策略,并加入适当的同步等待机制。

Python Appium 实践示例集

基础环境配置

确保已安装Python、Appium服务器、Android SDK或Xcode(iOS)。通过pip安装Appium Python客户端:

pip install Appium-Python-Client
示例1:连接设备并启动应用
from appium import webdriver
desired_caps = {'platformName

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/88996.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/88996.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/88996.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

给 Excel 整列空格文字内容加上前缀:像给文字穿衣服一样简单!

目录 步骤一&#xff1a;选中目标列 打开Excel表格并定位列点击列标题选中整列 步骤二&#xff1a;输入公式&#xff0c;变身“魔法” 在公式编辑栏输入公式按下回车键查看效果 步骤三&#xff1a;向下填充&#xff0c;批量处理 鼠标定位到单元格右下角按住鼠标左键向下拖动填充…

Spring Boot 启动原理揭秘:从 main 方法到自动装配

Spring Boot 启动原理揭秘&#xff1a;从 main 方法到自动装配 引言 Spring Boot 作为 Java 领域最流行的开发框架之一&#xff0c;凭借其“开箱即用”的特性极大地简化了 Spring 应用的搭建和部署。然而&#xff0c;尽管开发者在日常工作中频繁使用 Spring Boot 的启动类&…

OpenCV 与深度学习:从图像分类到目标检测技术

一、深度学习&#xff1a;从 “人工设计” 到 “自动学习”1.1 深度学习的定位&#xff1a;AI、机器学习与深度学习的关系人工智能&#xff08;AI&#xff09;&#xff1a;是一个宽泛的领域&#xff0c;目标是构建能模拟人类智能的系统&#xff0c;涵盖推理、感知、决策等能力。…

Docker 镜像推送至 Coding 制品仓库超时问题排查与解决

Docker 镜像推送至 Coding 制品仓库超时问题排查与解决 在将 Docker 镜像推送至 Coding 的制品仓库时&#xff0c;可能会遇到 docker push 命令超时失败的问题。但使用 curl -i http://xxx.coding.xxxx.xx 测试时&#xff0c;连接却能成功建立。以下是排查过程及解决方案。 问题…

https交互原理

Https 交互时序图&#xff1a;HTTPS 通信中结合 RSA 和 AES 加密的流程&#xff0c;本质是利用 RSA 的安全特性交换 AES 密钥&#xff0c;再用高效的 AES 加密实际数据传输。HTTPS 交互核心流程&#xff08;TLS/SSL 握手&#xff09; 1. 建立 TCP 连接 客户端通过 TCP 三次握手…

LSTM入门案例(时间序列预测)| pytorch实现

需求 假如我有一个时间序列&#xff0c;例如是前113天的价格数据&#xff08;训练集&#xff09;&#xff0c;然后我希望借此预测后30天的数据&#xff08;测试集&#xff09;&#xff0c;实际上这143天的价格数据都已经有了。这里为了简单&#xff0c;每一天的数据只有一个价…

WPS、Word加载项开发流程(免费最简版本)

文章目录1 加载项对比2 WPS 加载项2.1 本地开发2.1.1 准备开发环境2.1.2 新建 WPS 加载项项目2.1.3 运行项目2.2 在线部署2.2.1 编译项目2.2.2 部署项目2.2.3 生成分发文件2.2.4 部署分发文件2.3 安装加载项2.4 取消发布3 Word 加载项3.1 本地开发3.1.1 准备开发环境3.1.2 新建…

Flink SQL 性能优化实战

最近我们组在大规模上线Flink SQL作业。首先&#xff0c;在进行跑批量初始化完历史数据后&#xff0c;剩下的就是消费Kafka历史数据进行追数了。但是发现某些作业的追数过程十分缓慢&#xff0c;要运行一晚上甚至三四天才能追上最新数据。由于是实时数仓指标计算上线初期&#…

HTML 树结构(DOM)深入讲解教程

一、HTML 树结构的核心概念 1.1 DOM&#xff08;文档对象模型&#xff09;的定义 DOM&#xff08;Document Object Model&#xff09;是 W3C 制定的标准接口&#xff0c;允许程序或脚本&#xff08;如 JavaScript&#xff09;动态访问和更新 HTML/XML 文档的内容、结构和样式。…

用鼠标点击终端窗口的时候出现:0;61;50M0;61;50M0;62;50M0

在做aws webrtc viewer拉流压测的过程中&#xff0c;我本地打开了多个终端&#xff0c;用于连接EC2实例&#xff1a; 一个终端用于启动 ‘并发master脚本’、监控master端的cpu、mem&#xff1b;一个终端用于监控master端的带宽情况&#xff1b;一个终端用于监控viewer端的cpu、…

C++-linux 5.gdb调试工具

GDB调试工具 在C/C开发中&#xff0c;程序运行时的错误往往比编译错误更难定位。GDB&#xff08;GNU Debugger&#xff09;是Linux环境下最强大的程序调试工具&#xff0c;能够帮助开发者追踪程序执行流程、查看变量状态、定位内存错误等。本章将从基础到进阶&#xff0c;全面讲…

Update~Read PLC for Chart ~ Log By Shift To be... Alarm AI Machine Learning

上图~ 持续迭代 1、增加报警弹窗,具体到哪个值,双边规格具体是多少 2、实时显示当前值的统计特征,Max Min AVG ... import tkinter as tk from tkinter import simpledialog import time import threading import queue import logging from datetime import datet…

es的自定义词典和停用词

在 Elasticsearch 中&#xff0c;自定义词典是优化分词效果的核心手段&#xff0c;尤其适用于中文或专业领域的文本处理。以下是关于 ES 自定义词典的完整指南&#xff1a; 为什么需要自定义词典&#xff1f; 默认分词不足&#xff1a; ES 自带的分词器&#xff08;如 Standard…

微算法科技技术突破:用于前馈神经网络的量子算法技术助力神经网络变革

随着量子计算和机器学习的迅猛发展&#xff0c;企业界正逐步迈向融合这两大领域的新时代。在这一背景下&#xff0c;微算法科技&#xff08;NASDAQ:MLGO&#xff09;成功研发出一套用于前馈神经网络的量子算法&#xff0c;突破了传统神经网络在训练和评估中的性能瓶颈。这一创新…

一文读懂循环神经网络(RNN)—语言模型+读取长序列数据(2)

目录 读取长序列数据 为什么需要 “读取长序列数据”&#xff1f; 读取长序列数据的核心方法 1. 滑动窗口&#xff08;Sliding Window&#xff09; 2. 分段截取&#xff08;Segmentation&#xff09; 3. 滚动生成&#xff08;Rolling Generation&#xff09; 4. 关键信息…

Oracle Virtualbox 虚拟机配置静态IP

Oracle Virtualbox 虚拟机配置静态IP VirtualBox的网卡&#xff0c;默认都是第一个不能自定义&#xff0c;后续新建的可以自定义。 新建NAT网卡、host主机模式网卡 依次点击&#xff1a;管理->工具->网络管理器新建host主机模式网卡 这个网卡的网段自定义&#xff0c;创建…

Linux RAID1 创建与配置实战指南(mdadm)

Linux RAID1 创建与配置实战指南&#xff08;mdadm&#xff09;一、RAID1 核心价值与实战目标RAID1&#xff08;磁盘镜像&#xff09; 通过数据冗余提供高可靠性&#xff1a;当单块硬盘损坏时&#xff0c;数据不丢失支持快速阵列重建读写性能略低于单盘&#xff08;镜像写入开销…

MySQL数据库----函数

目录函数1&#xff0c;字符串函数2&#xff0c;数值函数3&#xff0c;日期函数4&#xff0c;流程函数函数 1&#xff0c;字符串函数 MySQL中内置了很多字符串函数 2&#xff0c;数值函数 3&#xff0c;日期函数 4&#xff0c;流程函数

1.2 vue2(组合式API)的语法结构以及外部暴露

vue2 vue3中可以写vue2的语法&#xff0c;vue2的结构像一个花盆里的根&#xff08;根组件App.vue&#xff09;&#xff0c;根上可以插上不同的枝杈和花朵&#xff08;组件&#xff09;。 组件的结构&#xff1a; // 这里写逻辑行为 <script lang"ts"> export d…

Swift 解 LeetCode 324:一步步实现摆动排序 II,掌握数组重排的节奏感

文章目录摘要描述题解答案题解代码&#xff08;Swift&#xff09;题解代码分析步骤一&#xff1a;排序数组步骤二&#xff1a;左右指针分段步骤三&#xff1a;按位置交错插入示例测试及结果示例 1示例 2示例 3&#xff08;边界情况&#xff09;时间复杂度分析空间复杂度分析总结…