App自动化测试_Python+Appium使用手册
一、Appium的介绍
二、Appium架构
Appium 是一个用Node.js编写的HTTP server,它创建、并管理多个 WebDriver sessions 来和不同平台交互,如 iOS ,Android等等.
Appium 开始一个测试后,就会在被测设备(手机)上启动一个 server ,监听来自 Appium server的指令. 每种平台像 iOS 和Android都有不同的运行、和交互方式。所以Appium会用某个桩程序“侵入”该平台,并接受指令,来完成测试用例的运行
三、Appium的工作原理
【工作过程】脚本请求 --> 4723端口appium server —> 解析参数给PC端4724端口 —> 发送给设备4724端口 —> 通过设备4724端口发给bootstrap.jar —> Bootstrap.jar把命令发给uiautomator![]()

三、Appium环境搭建
我目前使用的版本信息:
# JDK版本
jdk-8u261
# android SDK版本
installer_r24.4.1-windows.exe
# appium客户端
Appium-windows-1.15.1.exe
# Appium-Python-Client
pip install Appium-Python-Client==2.11.1# selenium版本
selenium==4.21.0
# 模拟器
nox_setup_v7.0.2.7_full.exe
网盘获取:
链接:https://pan.baidu.com/s/18uqZfmX9d9HqqSBIEM73uA?pwd=z5ak
提取码:z5ak
3.1、配置jdk环境
详见JDK配置文章:

3.2、android SDK环境
详见SDK配置文章:

3.3、安装appium客户端
Appium安装除了安装Appium客户端,还要在Python环境中安装Appium-Python-Client,其作用就是将 Python 与 appium 关联起来;
需要指定版本:pip install Appium-Python-Client==2.11.1
详见Appium配置文章:

3.5、下载模拟器
详见模拟器配置文章:

四、启动App
操作步骤:
- 启动桌面Appium客户端
- 启动模拟器或移动设施(确保连接adb)
- 启动Python脚本
4.1、启动桌面Appium客户端
双击 桌面Appium客户端-->启动服务器
4.2、启动模拟器或移动设施(确保连接adb)
ADB命令:ADB日常使用命令-CSDN博客
启动模拟器后,一般默认会已经连接adb,如果没有连接需要输入adb命令进行连接
# 验证是否连接成功
adb devices
# 建立连接
adb connect 127.0.1: 模拟器端口号〈逍遥模拟器21503〉
已连接
4.3、运行Python脚本,启动App
启动参数:
# 1.导入appium中的webdriver
from appium import webdriver
import timedef startUp():print('准备启动app')# 2. 启动参数,配置手机连接的参数内容,# 所有参数信息都是键值对的方式进行连接desire_caps = {"deviceName": "127.0.0.1:62001", # 参数1:当前设备的名称"platformName": "Android", # 参数2:系统"platformVersion": "7.1.2", # 参数3:系统版本号"appPackage": "com.android.contacts", # 参数4:启动的app名称(包名)"appActivity": ".activities.PeopleActivity t12", # 参数5:app界面名称"noReset": True,"unicodeKeyboard": True}# 3.发送连接请求driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_capabilities=desire_caps)# 等待时间,防止启动后立马关闭time.sleep(4)# 关闭驱动driver.quit()if __name__ == '__main__':startUp()
启动参数说明
待补充
五、元素定位工具
详见uiautomatorviewer.bat使用文章:

六、元素定位
6.1、单个元素定位:find_element
语法:
# 需要导包from selenium.webdriver.common.by import By
# 用法 --传递两个参数:一个是定位属性,一个是该属性的值
driver.find_element(By. 属性 ,' 属性值 ').操作方法
1.通过id定位
# resource-id 的值为iddriver . find_element ( By . ID , " xxxx " )
2.通过class_name定位
# 取class的属性值driver . find_element ( By . CLASS_NAME , " xxxx " )
3.通过link_text定位
# 取 text 属性值--文本属性driver . find_element ( By . LINK_TEXT , " xxxx " )
4.通过xpath定位
# 取元素xpath路径driver . find_element ( By . XPATH , " xxxx " )
# 使用文本属性比较实用(推荐)
driver.find_element(By.XPATH, '//*[@text="显示"]').click()
driver.find_element(By.XPATH, '//*[@text="亮度"]').click()
5.通过坐标定位driver.tap()
通过坐标定位有一定的局限性
-
优先:任意的元素都可以通过坐标进行定位操作
-
缺点:当手机的分辨率发生变化的时候,元素的坐标值也会发生变化
注意点:通过坐标定位的方法,一般使用场景是固定的机型或者固定的分辨率下进行自动化测试
driver.tap()
左边通过[(x,y)]形式传入
duration:表示触碰时间/ms
# 左上角driver.tap([(144,1327)], duration=100)# 右下角
driver.tap([(208, 1370)], duration=100)![]()
6.2、多个元素定位find_elements
driver . find_elements ( By . ID , "xxxxx" )[ 0 ]. click ()# 或list1 = driver . find_elements ( By . ID , "xxxxx" )list1 [ 0 ]. click ()
七、元素操作方法
Appium元素的操作方法与Selenium元素操作方法,基本一样
1. click():点击
# 模拟鼠标点击操作
driver.find_element(By.ID," xxxx ").click()
2. clear():清空
# 清空元素输入框中内容
driver.find_element(By.ID," xxxx ").clear()
3. send_keys():输入
# 往输入框中,输入内容值
driver.find_element(By.ID," xxxx ").send_keys("输入的内容")
4. text:获取文本属性值
# 获得元素的text内容
result = driver.find_element(By.XPATH," xxxx").text
print(result)
5. get_attribute():获取某个标签,元素的属性
# 获取标签xxx的元素的 class 属性值
driver.find_element(By.ID,'xxx').get_attribute('class')
6. size:获取元素的大小(宽、高)
# 获取元素的大小,得到一个字典如:{'height': 48, 'width': 640}
driver.find_element(By.ID,' xxxx ').size
7. location:获取元素的坐标
# 获取元素的坐标,得到的是一个字典{}
res = driver.find_element(By.ID,' xxxx ').locationprint(res) # {'x': 108, 'y': 380}
8. is_selected():判断元素是否被选中
# 选中返回True,否则返回False
res = driver.find_element(By.ID, 'xxxx').is_selected()
print(res) # True/False
9. is_enabled():判断元素是否被启用
# 判断元素是否被启用,返回True / False
res = driver.find_element(By.ID, 'xxxx').is_enabled()
print(res)
10. is_displayed():判断元素是否显示
#判断元素是否显示,返回True / False
res = driver.find_element(By.ID, 'xxxx').is_displayed()
print(res)
八、其它操作
8.1、操作应用包
1、判断是否安装
# 语法 返回True/False
driver.is_app_installed("应用的包名")# 可以简单做一个判断,然后进行安装或卸载
if driver.is_app_installed('io.manong.developerdaily'):driver.remove_app('io.manong.developerdaily')print('app卸载成功')
else:driver.install_app(r'D:\MS_App_auto_24_529\toutiao.apk')print('app安装成功')
2、安装应用
install_app("app的绝对路径")
3、卸载应用 remove_app("应用的包名")
4、获取当前操作的应用的界面名称
current_activity
8.2、操作屏幕页面
1.获取屏幕尺寸
方法:driver.get_window_size
# 得到的是一个字典,width是屏幕的宽度,height为屏幕的高度
dic = driver.get_window_size()print(dic ) #{'width': 1080, 'height': 1776}
2.页面滑动
方式1:坐标定位.swipe()
方法 : driver.swipe(x1, y1, x2, y2,duration)参数:(x1, y1):开始坐标,(x2, y2):结束坐标,duration:滑动时间注意 :滑动的坐标不能超过屏幕的宽高
# 获取屏幕尺寸得到所用坐标
def getSize(driver):x = driver.get_window_size()['width']y = driver.get_window_size()['height']x1 = x * 0.75x2 = x * 0.25y1 = y * 0.75y2 = y * 0.25return x1, y1, x2, y2# 完成上滑操作
def swipeUp(driver):x1, y1, x2, y2 = getSize(driver)driver.swipe(x1, y1, x1, y2, 100)
实现思路2:获取两个元素的坐标,在掉用swipe方法,从a元素 滚动到 b元素
# 获取元素坐标
a_dic = driver.find_element(By.XPATH,'//*[@text="WLAN"]').location # {'x': 144, 'y': 799}
b_dic = driver.find_element(By.XPATH,'//*[@text="通知"]').location # {'x': 144, 'y': 1471}# 将通知 滚动到 WLAN
driver.swipe(b_dic["x"], b_dic["y"], a_dic["x"], a_dic["y"], duration=100)
方式2: 通过元素的相对位置进行滚动
# 页面滚动
el1 = driver.find_element(By.XPATH, '//*[@text="显示"]')
el2 = driver.find_element(By.XPATH, '//*[@text="WLAN"]')
# 将"显示" 滚动到 "WLAN"位置
driver.scroll(el1, el2)
如图所示,将下面的“显示”滑动到上面的“WLAN”位置
3.获取界面的xml源码
page = driver.page_source()
assert '登陆成功' in page
4.拖拽操作 driver.drag_and_drop()
# 拖拽操作
el1 = driver.find_element(By.XPATH, '//*[@text="浏览器"]')
el2 = driver.find_element(By.XPATH, '//*[@text="开发者头条"]')
driver.drag_and_drop(el1, el2)
5、事件链TouchAction
作用:构建相对比较复杂的,连续的触摸行为
使用步骤通过" TouchAction" 类,创建事件链对象,然后传入 driver对象通过添加各种方法完成事件
- 按下
- 长按
- 移动
- 等待
- 松手
- 轻敲
- ...
# 事件链操作TouchAction
# 导包
from appium.webdriver.common.touch_action import TouchAction
# 实例化对象
action = TouchAction(driver)
time.sleep(1)
# 定位元素
ele1 = driver.find_element(By.XPATH, "//*[@text='通知']")
ele2 = driver.find_element(By.XPATH, "//*[@text='WLAN']")# 拖拽操作,将ele2,拖到 ele1位置
# press:按下操作 .wait(100):按下持续时间 move_to(ele1):移动到目标元素或坐标
action.press(ele1).wait(1000).move_to(ele2)
# 完成后,松手操作 release():松手动作
action.release()
# 提交事件链,生效
action.perform()# 再次滑动
ele3 = driver.find_element(By.XPATH, "//*[@text='电池']")
action.press(ele3).wait().move_to(ele1)
# 完成后,松手操作 release():松手动作
action.release()
# 提交事件链,生效
action.perform()# 点击安全
ele4 = driver.find_element(By.XPATH, "//*[@text='安全']")
ele4.click()
time.sleep(0.5)
# 通过事件链,绘制锁屏图案
# 点击屏幕锁定
driver.find_element(By.XPATH, "//*[@text='屏幕锁定']").click()
time.sleep(0.5)
# 点击图案
driver.find_element(By.XPATH, "//*[@text='图案']").click()
time.sleep(2)# 拖拽绘制图案
action.press(x=182, y=775)\.wait(100).move_to(x=449, y=1044) \.wait(100).move_to(x=190, y=1311) \.wait(100).move_to(x=714, y=1299)
6、截图/截屏
driver.get_screenshot_as_file('网络情况.png')
time.sleep(1)
driver.save_screenshot('网络情况2.png')
7、其它操作
键名 | 描述 | 键值 |
---|---|---|
KEYCODE_CALL | 拨号键 | 5 |
KEYCODE_ENDCALL | 挂机键 | 6 |
KEYCODE_HOME | 按键 Home | 3 |
KEYCODE_MENU | 菜单键 | 82 |
KEYCODE_BACK | 返回键 | 4 |
KEYCODE_SEARCH | 搜索键 | 84 |
KEYCODE_CAMERA | 拍照键 | 27 |
KEYCODE_FOCUS | 拍照对焦键 | 80 |
KEYCODE_POWER | 电源键 | 2 |
# - 获取手机的网络信息:网络信息三种模式分别对应数值# 飞行模式: 1# 无线网络: 2# 移动网络: 4# 网络情况可以进行组合: 3=1+2,6=2+4
print(driver.network_connection)
driver.set_network_connection(2)
time.sleep(1)
print(driver.network_connection)
print(driver.device_time)
driver.open_notifications()
九、时间等待
十、APP自动化框架设计思想
参考文档:
Appium使用教程_Android篇-CSDN博客
相关文章:

App自动化测试_Python+Appium使用手册
一、Appium的介绍 Appium是一款开源的自动化测试工具,支持模拟器和真机上的原生应用、混合应用、Web应用;基于Selenium二次开发,Appium支持Selenium WebDriver支持的所有语言(java、 Object-C 、 JavaScript 、p hp、 Python等&am…...

k8s-部署对象存储minio
环境信息 minio版本 :最新 k8s 版本1.22 使用nfs作为共享存储 一.单节点安装包部署 脚本部署,一键部署,单节点应用于数据量小,一些缓存存储,比如gitlab-runner的产物数据,maven的打包依赖数据 #!/bin/bash# 步骤…...

go常用命令
创建一个module(逻辑概念) #The go mod init command initializes and writes a new go.mod file in the current directory, in effect creating #a new module rooted at the current directory. #specify a module path that serves as the module’s name. go mod initclon…...

【中年危机】程序猿自救指南
中年危机,一个听起来就充满挑战的词汇,它不仅仅是一个年龄的标记,更是一个个人成长和职业发展的转折点。 构架个人品牌: 学会打造IP个人品牌是职业生涯中的重要资产。在中年时期,你已经积累了丰富的经验和知识&#x…...

vueRouter路由总结
https://blog.csdn.net/qq_24767091/article/details/119326884...

算法工程师需要学习C++的哪些知识?
在开始前刚好我有一些资料,是我根据网友给的问题精心整理了一份「C的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给大家!!!以下是算法工程师需要学习的一些…...

CTF网络安全大赛简单的web抓包题目:HEADache
题目来源于:bugku 题目难度:简单 题目 描 述: > Wanna learn about some types of headache? > Lets dig right into it! 下面是题目源代码: <!DOCTYPE html> <html> <head><meta charset"utf-8"&…...

Qt Creator创建Python界面工程并打包为可执行exe文件
Qt Creator创建Python界面工程并打包为可执行exe文件_qtcreator创建python工程-CSDN博客...

基于单片机的步进电机控制系统的研究
摘要: 步进电机控制作为一种电机控制系统的重要模式,属于现代数字化控制的重要手段,其应用已经相当广泛。步进电机属于感应电机类,利用电子电路将直流电分为分时供电、多相时序供电控制电流,利用这种电流为电机供电,驱使电机工作。步进电机不能够在常规模式下使用,必须通过双环…...

BioPorto胰高血糖素样肽-1抗体(GLP-1)
丹麦BioPorto Diadnostics公司致力于提供世界领先的GLP-1抗体。基于结合GLP-1位点的不同,他们筛选出了不同的抗GLP-1抗体。有的抗体可以同时结合GLP-1的活性形式和非活性形式,有的专门结合生物活性形式的GLP-1。在开发和检测GLP-1相关治疗的过程中&#…...

Go 语言字符串及 strings 和 strconv 包
在 Go 语言编程中,字符串是最基本、最常用的数据类型之一。无论是处理用户输入、读取文件内容,还是生成输出,字符串操作无处不在。为了方便开发者对字符串进行各种操作,Go 语言提供了强大的 strings 包和 strconv 包。strings 包包…...

政府窗口服务第三方评估报告如何写
撰写政府窗口服务第三方评估报告需要结构清晰、内容详实,并包含对评估过程和结果的详细描述以及改进建议。以下是第三方评估机构民安智库(第三方社会评估调研公司)给出的一个政府窗口服务第三方评估报告简单的示例: 一、封面 报…...

若依前后端分离Spring Security新增手机号登录
备忘贴 转自:【若依RuoYi短信验证码登录】汇总_数据库_z_xiao_qiang-RuoYi 若依 配置Security: 按照Security的流程图可知,实现多种方式登录,只需要重写三个主要的组件,第一个用户认证处理过滤器,第二个用户认证tok…...

Oracle操作扩可变字符长度交易影响分析-较小
使用AI帮助学习知识 以下知识来至AI oracle 一张大表,对可变字符串长度从10扩到20位,oracle底层存储是否会发生变化,先锁表,更新表字典信息,然后会不会重新整理表,在有交易的情况下导致大量交易失效&#…...

全栈工程师需要具备哪些技能?
概论: 全栈工程师是一位能够从头到尾构建 Web 应用程序的工程师,能独立完成产品。技术包括前端部分、后端部分和应用程序所在的基础架构。他们在整个技术栈中工作,并了解其中的每个部分。从需求分析开始,到概要设计,详…...

用java实现客服聊天+网络爬虫下载音乐(java网络编程,io,多线程)
一 灵感: 在2022年的暑假,也就是我即将迈进高三的那个暑假,我并没有察觉自己应该要学习了,还是和过往的暑假一样玩着王者荣耀,凌晨2点睡觉,中午12点起床。我依稀记得这种状态一直持续到8月19。然而离开学还…...

基于springboot+vue的医院信息管理系统
开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…...

乡村振兴与农业科技创新:加大农业科技研发投入,推动农业科技创新,促进农业现代化和美丽乡村建设
一、引言 在当代中国,乡村振兴已成为国家发展的重要战略之一。作为国民经济的基础,农业的发展直接关系到国家的稳定和人民的福祉。随着科技的不断进步,农业科技创新在推动农业现代化和美丽乡村建设中发挥着越来越重要的作用。本文旨在探讨如…...

Java 雪花算法:分布式唯一ID生成的魔法秘籍
欢迎来到本次博客的旅程,今天我们要揭开一个神秘算法的面纱,它就是在分布式系统中广受欢迎的——雪花算法(Snowflake)。这个算法不是用来预测雪花的形状,而是用来生成唯一的ID,保证在分布式系统中ÿ…...

mybatis配置环境流程
mybatis配置环境流程 为啥要用mybatis:通过Mybatis实现快速访问后端pgsql、mysql等数据库。 1.修改pom.xml,添加mybatis相关依赖 <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-s…...

UE5增强输入系统入门
UE4直接在项目设置里设置的轴映射和操作映射在UE5中被标记为废弃,改为使用增强输入系统。 这两天学习了下蓝图和c中增强输入系统的使用,在这里分享一下。 学习使用的模板是第三人称模板(蓝图/c),代码蓝图都参考的模板。 增强输入系统 UE5…...

Python 语法好乱:深度解析与应对策略
Python 语法好乱:深度解析与应对策略 Python,作为一门简洁明了的编程语言,广受编程初学者的喜爱。然而,随着学习的深入,许多学习者会发现Python的语法似乎并不像初看起来那么简单,甚至有时会感到“好乱”。…...

移动端框架:加速移动应用开发与提升跨平台兼容性
在当今快速发展的移动应用领域,开发者们面临着如何快速构建、维护并发布跨平台应用的挑战。为了应对这一挑战,移动端框架应运而生,它们不仅加速了移动应用的开发流程,还提升了应用的跨平台兼容性,并确保了应用性能与原…...

Linux systemctl:掌握软件启动和关闭的利器
Linux systemctl:掌握软件启动和关闭的利器 在 Linux 操作系统中,systemctl 是一个强大的工具,用于管理系统服务的启动、停止和状态监控。本篇博客将深入介绍 systemctl 的使用方法,帮助你更好地掌握软件的启动和关闭。 1. syst…...

Jmeter干货分享:当你的Log viewer不显示日志时,可能是引入的Jar包冲突导致
问题描述 近期使用Jmeter时发现了一个非常奇怪的问题,就是Jmeter是可以正常使用运行脚本,但是在Log viewer中确没有任何日志,如下图: 问题排查过程 真是百思不得其解啊,在网上各种获取资料,大多数都是说跟…...

网络编程TCP
White graces:个人主页 🙉专栏推荐:Java入门知识🙉 🙉 内容推荐:Java网络编程(下)🙉 🐹今日诗词: 壮士当唱大风哥, 宵小之徒能几何?🐹 ⛳️点赞 ☀️收藏⭐️关注💬卑微…...

C++中的迭代器
目录 摘要 迭代器类别 1. 输入迭代器(Input Iterator) 2. 输出迭代器(Output Iterator) 3. 前向迭代器(Forward Iterator) 4. 双向迭代器(Bidirectional Iterator) 5. 随机访…...

8.1 Go 包的概念与使用
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…...

第一篇【传奇开心果系列】AI工业应用经典算法和Python示例:基于AI的智能制造技术经典算法与Python实践
传奇开心果博文系列 系列博文目录AI工业应用经典算法和Python示例系列 博文目录前言一、AI在智能制造方面的应用场景介绍二、基于AI的智能制造技术经典算法介绍三、支持向量机机器学习算法Python示例代码四、随机森林机器学习算法Python示例代码五、深度学习算法Python示例代码…...

Mathtype插入编号的高级格式会重置之前的简单格式的问题
文章标题没说人话,大致意思是: 先以简单格式插入几个编号 再设置高级格式的编号时,即使没有选择插入编号,在点击下图的确定键时,会连带前面的简单公式一并更新 我在网上没有找到相关的问题,即使关闭了…...