当前位置: 首页 > news >正文

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

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.dtcms.com/a/277020.html

相关文章:

  • Vue3 实现文件上传功能
  • HarmonyOS组件/模板集成创新活动-开发者工具箱
  • Vue配置特性(ref、props、混入、插件与作用域样式)
  • FusionOne HCI 23 超融合实施手册(超聚变超融合)
  • 第七章 算法题
  • NO.4数据结构数组和矩阵|一维数组|二维数组|对称矩阵|三角矩阵|三对角矩阵|稀疏矩阵
  • 电源中的声学-噪声,如何抑制开关电源的噪声
  • 飞算JavaAI:开启 Java 开发 “人机协作” 新纪元
  • 二叉树算法详解和C++代码示例
  • 项目合作复盘:如何把项目经验转化为可复用资产
  • 【C++】第十五节—一文详解 | 继承
  • ArkUI Inspector工具用法全解析
  • 【保姆级图文详解】Spring AI 中的工具调用原理解析,工具开发:文件操作、联网搜索、网页抓取、资源下载、PDF生成、工具集中注册
  • 在 JetBrains 系列 IDE(如 IntelliJ IDEA、PyCharm 等)中如何新建一个 PlantUML 文件
  • jEasyUI 创建带复选框的树形菜单
  • NLP-迁移学习
  • 【PyMuPDF】PDF图片处理过程内存优化分析
  • RHCIA第二次综合实验:OSPF
  • 电阻抗成像肺功能测试数据分析与直方图生成
  • 攻防世界——Web题 very_easy_sql
  • Rust 模块系统:控制作用域与私有性
  • python 虚拟环境 Anaconda Miniconda
  • 大模型的Temperature、Top-P、Top-K、Greedy Search、Beem Search
  • jeepay开源项目开发中金支付如何像其他支付渠道对接那样简单集成,集成服务商模式,极简集成工具。
  • AI驱动的软件工程(中):文档驱动的编码与执行
  • 深入解析 ArrayList
  • XGBoost三部曲:XGBoost原理
  • Docker一键安装中间件(RocketMq、Nginx、MySql、Minio、Jenkins、Redis)脚步
  • Transformer 小记(一):深入理解 Transformer 中的位置关系
  • 【PTA数据结构 | C语言版】字符串截取子串操作