Appium 3.0:跨平台移动自动化测试框架全面解析

news/2025/10/19 21:37:52/文章来源:https://www.cnblogs.com/qife122/p/19151466

Appium 3.0:跨平台移动自动化测试框架全面解析

项目概述

Appium 是一个开源的跨平台自动化测试框架,基于 WebDriver 协议,为各种移动、桌面和 IoT 平台提供自动化测试能力。Appium 采用模块化和可扩展的架构,支持多种编程语言,拥有完整的驱动和插件生态系统。

核心特性

  • 跨平台支持:支持 iOS、Android、桌面应用等多种平台
  • 多语言支持:提供 Python、Java、JavaScript、Ruby、C# 等客户端库
  • 模块化架构:通过驱动和插件系统实现功能扩展
  • WebDriver 协议:遵循 W3C WebDriver 标准
  • 丰富的生态系统:包含多种官方和第三方驱动、插件
  • 类型安全:完整的 TypeScript 类型定义支持

功能特性

核心功能

  • 原生应用自动化:支持 iOS 和 Android 原生应用的自动化测试
  • 混合应用测试:能够测试包含 WebView 的混合应用
  • 移动 Web 测试:支持移动浏览器中的网页测试
  • 桌面应用自动化:扩展支持桌面应用程序测试
  • IoT 设备支持:为物联网设备提供自动化测试能力

扩展生态系统

  • 驱动系统:为不同平台提供专门的自动化驱动
  • 插件机制:通过插件扩展服务器功能
  • 客户端库:多种编程语言的客户端实现
  • 检查器工具:可视化元素检查和测试录制

安装指南

系统要求

  • Node.js v20.19.0 或更高版本
  • 各平台对应的开发工具(如 Android SDK、Xcode)

安装步骤

  1. 安装 Appium
npm install -g appium
  1. 安装驱动和插件
# 安装 Android 驱动
appium driver install uiautomator2# 安装 iOS 驱动  
appium driver install xcuitest# 安装常用插件
appium plugin install images
appium plugin install execute-driver
  1. 验证安装
appium --version
appium driver list
appium plugin list

平台特定说明

  • Android:需要配置 ANDROID_HOME 环境变量
  • iOS:需要安装 Xcode 和开发者工具
  • Windows:可能需要额外配置 .NET 环境

使用说明

基础示例

JavaScript (WebdriverIO)

const {remote} = require('webdriverio');const capabilities = {platformName: 'Android','appium:automationName': 'UiAutomator2','appium:deviceName': 'Android','appium:appPackage': 'com.android.settings','appium:appActivity': '.Settings',
};async function runTest() {const driver = await remote({hostname: 'localhost',port: 4723,capabilities});try {const appsItem = await driver.$('//*[@text="Apps"]');await appsItem.click();} finally {await driver.deleteSession();}
}

Python

from appium import webdriver
from appium.options.android import UiAutomator2Optionscapabilities = dict(platformName='Android',automationName='uiautomator2',deviceName='Android',appPackage='com.android.settings',appActivity='.Settings'
)driver = webdriver.Remote('http://localhost:4723', options=UiAutomator2Options().load_capabilities(capabilities))
el = driver.find_element(by=AppiumBy.XPATH, value='//*[@text="Apps"]')
el.click()
driver.quit()

Ruby

require 'appium_lib_core'CAPABILITIES = {platformName: 'Android',automationName: 'uiautomator2',deviceName: 'Android',appPackage: 'com.android.settings',appActivity: '.Settings'
}core = ::Appium::Core.for capabilities: CAPABILITIES
driver = core.start_driver server_url: 'http://localhost:4723'
driver.wait { |d| d.find_element :xpath, '//*[@text="Apps"]' }.click
driver.quit

服务器配置

通过配置文件或命令行参数配置 Appium 服务器:

// .appiumrc.json
{"server": {"address": "127.0.0.1","port": 4723,"base-path": "/","allow-cors": true,"log-level": "info","use-drivers": ["uiautomator2", "xcuitest"],"use-plugins": ["images", "execute-driver"]}
}

核心代码解析

基础驱动架构

// @appium/base-driver 提供基础驱动类
const {BaseDriver} = require('appium/driver');class MyCustomDriver extends BaseDriver {constructor(opts = {}) {super(opts);this.desiredCapConstraints = {platformName: {presence: true,isString: true},app: {isString: true}};}async createSession(caps, ...args) {const [sessionId, customCaps] = await super.createSession(caps, ...args);// 自定义会话创建逻辑await this.startDevice();return [sessionId, customCaps];}async startDevice() {// 启动设备连接this.logger.info('Starting device session');}
}

插件系统实现

// @appium/base-plugin 提供基础插件类
const {BasePlugin} = require('appium/plugin');class MyCustomPlugin extends BasePlugin {static executeMethodMap = {'/session/:sessionId/my_custom_command': {POST: {command: 'myCustomCommand',payloadParams: {required: ['param1']}}}};async myCustomCommand(next, driver, sessionId, param1) {this.logger.info(`Executing custom command with param: ${param1}`);// 自定义插件逻辑return {success: true, result: 'Custom command executed'};}async handle(next, driver, cmdName, ...args) {// 拦截和处理命令this.logger.info(`Intercepting command: ${cmdName}`);const result = await next();this.logger.info(`Command ${cmdName} completed`);return result;}
}

工具函数库

// @appium/support 提供通用工具函数
const {fs, util, logger} = require('appium/support');class ImageUtils {constructor() {this.logger = logger.getLogger('ImageUtils');}async compareImages(image1Path, image2Path) {try {const image1 = await fs.readFile(image1Path);const image2 = await fs.readFile(image2Path);// 使用 OpenCV 进行图像比较const {score} = await getImagesSimilarity(image1, image2);this.logger.info(`Image similarity score: ${score}`);return score > 0.8; // 返回相似度是否超过阈值} catch (error) {this.logger.error('Image comparison failed:', error);throw error;}}
}

配置管理系统

// @appium/schema 提供配置验证
const {AppiumConfigJsonSchema} = require('@appium/schema');
const ajv = new Ajv();class ConfigManager {constructor() {this.validator = ajv.compile(AppiumConfigJsonSchema);}validateConfig(config) {const valid = this.validator(config);if (!valid) {throw new Error(`Invalid configuration: ${JSON.stringify(this.validator.errors)}`);}return config;}async loadConfig(configPath) {const configData = await fs.readFile(configPath, 'utf8');const config = JSON.parse(configData);return this.validateConfig(config);}
}

测试支持框架

// @appium/driver-test-support 提供测试工具
const {driverE2ETestSuite, TEST_HOST, getTestPort} = require('@appium/driver-test-support');describe('MyDriver E2E Tests', function() {const capabilities = {platformName: 'MyPlatform','appium:automationName': 'MyDriver','appium:app': 'test.app'};driverE2ETestSuite(MyDriver, capabilities, {host: TEST_HOST,port: async () => await getTestPort()});it('should handle custom commands', async function() {const result = await this.driver.executeScript('myCustomScript', []);expect(result).to.have.property('success', true);});
});

这些核心代码展示了 Appium 的模块化架构和扩展性设计,为开发自定义驱动和插件提供了坚实的基础框架。
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)

公众号二维码

公众号二维码

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

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

相关文章

德国州政府全面弃用微软办公套件,改用开源方案

德国州政府全面弃用微软办公套件,改用开源方案德国州政府全面弃用微软办公套件,改用开源方案来源: OSCHINA 编辑: 局 2025-10-16 19:24:043德国石勒苏益格 - 荷尔斯泰因州宣布,已正式完成从微软 Outlook 和 Exchang…

DAPO代码实现浅析

参考verl对dapo的实现,首先咱们看一下入口.sh和.py文件,在./recipe/dapo/文件夹中有以下目录 . ├── config │ ├── dapo_megatron_trainer.yaml │ └── dapo_trainer.yaml ├── dapo_ray_trainer.py …

[KaibaMath]1011 关于收敛数列保号性的证明

[KaibaMath]1011 关于收敛数列保号性的证明收敛数列保号性是描述收敛数列的极限符号与数列“后期项”符号关系的核心性质,即极限的非零符号能“保证”数列从某一项开始的所有项与极限同号。下面给出证明。

赛前训练 12 extra 树上差分倍增

A 树上差分板子. B 每个点只有一条出边的有向图可以看作树 基于上述结论,我们直接倍增维护 \(\min,\operatorname{sum}\) 即可.实现 #include <cstdio> #include <iostream> #include <algorithm> #…

塔吊施工人员操作合规性监测!思通数科 AI 卫士实时守护作业安全

塔吊施工中,人员操作合规性是安全管理的关键环节,但传统人工监管常面临 “监管范围有限、异常难实时发现” 的痛点:作业人员是否按规范穿戴防护装备(安全帽、防护服、防护手套),靠远处观察难判断穿戴完整性(如安…

Dos命令1

常用的dos命令 我不懂

题解:P1073 [NOIP 2009 提高组] 最优贸易

题目传送门 绝世好题 让我学会了分层图的真正用法 以前都只会自作聪明地分两层: 美其名曰【正图】【反图】 现在知道了还有这种神奇的建图方法!理解题意: 有向图 给定起点终点 求路径上两点买卖东西最大收益 思路:…

吩咐

吩咐rt。不知道要写些什么。 Q/A 或者别的。 记忆力可能比较差,可能会有内容错乱。Q以下是博客签名,正文无关 本文来自博客园,作者:Wy_x,转载请在文首注明原文链接:https://www.cnblogs.com/Wy-x/p/19151449 版权…

互评五

一、数据存储结构不同 ArrayImpl: 使用固定大小的数组 Student[] students ListImpl: 使用动态数组 ArrayList students 构造函数差异 ArrayImpl: 需要指定初始大小 public StudentDaoArrayImpl(int size) ListImpl: 无…

ACS ACR122 0 是啥

ACS ACR122 0 是啥你提到的 “ACS ACR122 0”,实际上指的是一个 NFC 读卡器(RFID Reader)。 下面我详细给你讲清楚它是什么、怎么用、以及它为什么会在系统里显示成那个名字。🪪 一、设备全称 ACS ACR122U NFC Re…

C++ std::forwardT 的使用

C++ std::forwardC++ std::forward 的使用 C++真实一门细节比较多的语言,稍不注意就会出现奇怪请琢磨不透的bug,这时候就说明你的C++基础不扎实。 C++ lvalue rvalue std::string hello = "Hello World";顾…

机器人技术新前沿:自动驾驶路径规划算法解析

本文深入探讨了自动驾驶机器人出租车技术的核心算法,包括基于机器学习的路径规划、环境感知与行为预测系统,并对比了火星探测器与城市自动驾驶在技术挑战上的差异。机器人技术新前沿 某中心子公司Zoox首席软件工程师…

前端框架文档新思路:基于源码解析的自动化方案

项目背景 最近我们团队自研了一个基于 React 的 H5 前端框架,领导让我来负责编写框架的使用文档。我选择了 dumi 来搭建文档站点,大部分内容都是手动写 Markdown 来介绍各种功能,包括:初始化、目录结构、生命周期、…

tryhackme-预安全-网络基础知识-数据包和帧-07

tryhackme-Pre Security-Pre Security-Network Fundamentals-Packets & Frames 房间地址:https://tryhackme.com/room/packetsframes 这是网络安全入门的基础模块的计算机科学基础知识:Packets & Frames(数…

Agilent E363x 系列

Agilent E363x 系列⚙️ 一、Agilent E363x 是什么设备 Agilent E363x(也写作 E3630 / E3631 / E3632 / E3633 / E3634 等型号) 是一系列由 Agilent Technologies(现 Keysight Technologies) 出品的 👉 可编程直流…

嗣澳——扫,墨依奥——描,希伊桉——线

rt: 扫描线 定义 扫描线顾名思义就是用线扫描,维护区间的长度。它一般被用来解决图形面积,周长问题。 rt:把整个矩形分成如图各个颜色不同的小矩形,小矩形的高是扫过的距离,然而矩形的水平宽一直在变化。 给每一个…

迈向零信任存储:基于RustFS构建内生安全的数据架构

迈向零信任存储:基于RustFS构建内生安全的数据架构在数据泄露事件频发的当下,传统边界安全模型已不足以保护企业核心数据资产。本文将深入解析如何基于RustFS构建​内生安全的零信任存储架构,实现从“信任网络”到“…

服务器被攻击!原因竟然是他?真没想到...

国庆回来之后服务器就被搞了,一直没用完过的流量,竟然神奇般就被耗费完了,这就要承担每天被扣费的问题了,而且正常用户访问也很慢。 于是赶紧用官方的安全工具扫描了服务器,没发现问题。之后看了 Nginx 的访问日志…

得到的眼泪学会了哭泣 得到的悲伤缓慢摧残肉体 被所爱之人踩在地

test23 前后缀排序sort 复制数组然后 sa 即可。 像忘了哪个题目一样,先考虑删除 \(s_i,s_k\) 哪个会更小,不妨令 \(i<j\)。考虑 \(s_j\) 是 \(i\) 后面第一个不同的字符,发现删除点在 \([i+1,j-1],j,[j+1,n]\) 的…