APP自动化测试框架-UiAutomator2基础
ccwgpt 2025-04-23 22:32 20 浏览 0 评论
前言
很早以前,我用uiautomator+java实践过Android APP自动化测试,不过今天要提的不是uiautomator,而是uiautomator2。听起来uiautomator2像是uiautomator的升级版,但是这两款框架仅仅是名字上比较相似,实际上没有任何关联。
一、uiautomator/uiautomator2的前生今世
项目地址:
https://github.com/openatx/uiautomator2
1.官方文档介绍
2.梳理一下脉络
- 先有的谷歌uiautomator,但是只支持java;
- 后来一个名为hexiaocong的开发者基于uiautomator封装了python版本,支持python代码运行;
- 而受其启发,uiautomator2作者开发了uiautomator2。所以它们的诞生顺序应该是:uiautomator(谷歌版)-->uiautomator(python版)-->uiautomator2
3.三款框架对比
框架 | 支持语言 | 特点 |
uiautomator | java | 谷歌开源,仅支持Android |
xiaocong/uiautomator | python | 开源,仅支持Android |
uiautomator2 | python | 开源,仅支持Android |
二、uiautomator2简介
1.项目组成
- uiautomator-server:主服务
- minicap:实现实时屏幕投屏,以及实时截图
- minitouch:用于精确实时控制设备
- atx-agent:运行在设备上的驻守程序,go开发,用于保活设备上相关的服务
- weditor:类似于uiautomatorviewer,专门为本项目开发的辅助编辑器
2.工作原理
1)各部分职责
- Python:编写脚本,向移动设备发起http请求;
- 移动设备:运行了封装了uiautomator2的http服务,解析python脚本发起的请求,并转化成uiautomator2可识别的代码;
2)运行过程
- 移动设备上运行atx-agent守护进程,随后atx-agent启动uiautomator2服务,默认7912端口进行监听;
- 在PC上编写python脚本并执行(相当于发送 HTTP 请求到移动设备的 server 端);
- 移动设备通过 WIFI 或 USB 接收到 PC 上发来的 HTTP 请求,执行指定的操作,从而操作移动设备;
三、环境搭建
1.安装uiautomator2
pip install uiautomator2
pip install -U weditor # 安装weditor
2.初始化设备
python -m uiautomator2 init
初始化成功会出现如下提示
当PC或Linux服务器连接了多台adb device的情况下,“python -m uiautomator2 init”默认初始化的是所有设备,若指定设备初始化,则需使用“--serial”参数:
python -m uiautomator2 init --serial $SERIAL # $SERIAL为手机序列号,可通过adb devices查看
3.init时都干了啥?
执行“python -m uiautomator2 init”命令,会自动往手机上安装一堆东西:
- app-uiautomator.apk
- app-uiautomator-test.apk
- atx-agent
- minicap
- minitouch
更多信息详见:
https://github.com/openatx/uiautomator2/wiki/Manual-Init
四、基础操作
1.连接设备
uiautomator2提供了3种连接方式
1)通过WiFi连接
import uiautomator2 as u2
d = u2.connect('10.0.0.1') # alias for u2.connect_wifi('10.0.0.1')
print(d.info)
2)通过USB连接
import uiautomator2 as u2
d = u2.connect('123456f') # alias for u2.connect_usb('123456f')
print(d.info)
3)通过ADB WiFi连接
import uiautomator2 as u2
d = u2.connect_adb_wifi("10.0.0.1:5555")
# 等同于
# + Shell: adb connect 10.0.0.1:5555
# + Python: u2.connect_usb("10.0.0.1:5555")
2.命令行工具
1)截图
uiautomator2 screenshot test.jpg
2)获取当前APP报名及Activity
uiautomator2 current
3)卸载应用
uiautomator2 uninstall <package-name> # 卸载一个包
uiautomator2 uninstall <package-name-1> <package-name-2> # 卸载多个包
uiautomator2 uninstall --all # 全部卸载
4)停止应用
$ uiautomator2 stop com.example.app # 停止一个app
$ uiautomator2 stop --all # 停止所有的app
3.元素定位
1)常见定位方式
ui2支持 android 中 UiSelector 类中的所有定位方式,详细可以查看官网:
https://developer.android.com/reference/android/support/test/uiautomator/UiSelector,以下仅列出几种常见的定位方式:
定位方式 | 描述 |
text | 通过文本定位 |
textMatches | 通过文本正则匹配定位 |
className | 通过类名定位 |
classNameMatches | 通过类名正则匹配定位 |
description | 通过desc属性定位 |
descriptionMatches | 通过desc属性正则匹配定位 |
resourceId | 通过resourceId定位 |
resourceIdMatches | 通过resourceId正则匹配定位 |
2)子元素定位及兄弟元素定位
① 子元素定位-child
#查找类名为android.widget.ListView下的Bluetooth元素
d(className="android.widget.ListView").child(text="Bluetooth")
# 下面这两种方式定位有点不准确,不建议使用
d(className="android.widget.ListView")\
.child_by_text("Bluetooth",allow_scroll_search=True)
d(className="android.widget.ListView").child_by_description("Bluetooth")
② 兄弟元素定位-sibiling
#查找与google同一级别,类名为android.widget.ImageView的元素
d(text="Google").sibling(className="android.widget.ImageView")
③ 链式调用
d(className="android.widget.ListView", resourceId="android:id/list") \
.child_by_text("Wi-Fi", className="android.widget.LinearLayout") \
.child(className="android.widget.Switch") \
.click()
3)相对定位
d(A).left(B),# 选择A左边的B
d(A).right(B),# 选择A右边的B
d(A).up(B), #选择A上边的B
d(A).down(B),# 选择A下边的B
#选择 WIFI 右边的开关按钮
d(text='Wi-Fi').right(resourceId='android:id/widget_frame')
4) Xpath定位
Java uiautoamtor中默认不支持xpath,这是属于ui2的扩展功能,速度会相比其它定位方式慢一些。在xpath定位中,ui2中的description 定位需要替换为content-desc,resourceId 需要替换为resource-id
# 只会返回一个元素,如果找不到元素,则会报XPathElementNotFoundError错误
# 如果找到多个元素,默认会返回第0个
d.xpath('//*[@resource-id="com.android.launcher3:id/icon"]')
# 如果返回的元素有多个,需要使用all()方法返回列表
# 使用all方法,当未找到元素时,不会报错,会返回一个空列表
d.xpath('//*[@resource-id="com.android.launcher3:id/icon"]').all()
4.元素常用API
方法 | 描述 | 返回值 | 备注 |
exists() | 判断元素是否存在 | True,Flase | @property |
info() | 返回元素的所有信息 | 字典 | @property |
get_text() | 返回元素文本 | 字符串 | |
set_text(text) | 设置元素文本 | None | |
clear_text() | 清空元素文本 | None | |
center() | 返回元素的中心点位置 | (x,y) | 基于整个屏幕的点 |
send_keys() | 发送文本 |
用法示例:
d(test="Settings").exists
d.exists(text='Wi-Fi',timeout=5)
5.设备交互
1)单击/双击
d(text='Settings').click() # 单击
d.double_click(x, y)
d.double_click(x, y, 0.1) # 双击默认时间间隔0.1s
2)长按
d(text='Settings').longclick() # 长按
3)滑动
# "left", "right", "up", "down"
d(text="Settings").swipe("up", steps=20) # 元素向上滑动,步长20
d(text="Settings").swipe("down", steps=20) # 元素向下滑动
d(text="Settings").swipe("left", steps=20) # 元素向左滑动
d(text="Settings").swipe("right", steps=20) # 元素向右滑动
4)拖动
d(text="Settings").drag_to(text="Clock", duration=0.25) # 拖动到某个元素,时长0.25秒
d(text="Settings").drag_to(877,733) # 拖动到屏幕某个坐标点,duration时长默认0.5秒
5)双指操作(元素放大/缩小)
d(text="Settings").pinch_in() # 缩小
d(text="Settings").pinch_out() # 放大
6)等待元素出现/消失
d(text="Settings").wait(timeout=3.0) # 等待元素出现
d(text='Settings').wait_gone(timeout=20) # 等待元素消失,返回True False,timout默认为全局设置的等待时间
7)屏幕滚动
# 垂直滚动到页面顶部/横向滚动到最左侧
d(scrollable=True).scroll.toBeginning()
d(scrollable=True).scroll.horiz.toBeginning()
# 垂直滚动到页面最底部/横向滚动到最右侧
d(scrollable=True).scroll.toEnd()
d(scrollable=True).scroll.horiz.toEnd()
# 垂直向后滚动到指定位置/横向向右滚动到指定位置
d(scrollable=True).scroll.to(description="指定位置")
d(scrollable=True).scroll.horiz.to(description="指定位置")
# 垂直向前滚动(横向同理)
d(scrollable=True).scroll.forward()
# 垂直向前滚动到指定位置(横向同理)
d(scrollable=True).scroll.forward.to(description="指定位置")
# 滚动直到System元素出现
d(scrollable=True).scroll.to(text="System")
8)文本框操作
d.send_keys("test")
d.clear_text() # 清空输入框
9)toast操作
# 获取toast,当没有找到toast消息时,返回default内容
d.toast.get_message(timout=5,default='no toast')
# 清空toast缓存
d.toast.reset()
10)监控操作
# 移除ANR的监控
d.watcher.remove("ANR")
# 移除所有的监控
d.watcher.remove()
# 开始后台监控
d.watcher.start()
d.watcher.start(2.0) # 默认监控间隔2.0s
# 强制运行所有监控
d.watcher.run()
# 停止监控
d.watcher.stop()
# 停止并移除所有的监控,常用于初始化
d.watcher.reset()
更多api详见:
https://github.com/openatx/uiautomator2
五、weditor元素定位
1.启动weditor服务
python -m weditor
2.访问weditor
默认端口17310,访问地址:http://localhost:17310/,手机连接PC(确保已开启USB调试模式),点击Connect连接设备,当Connect图标变为绿色表示连接成功。
3.界面调试
weditor提供了所操作即所得式的元素定位方式,当双击屏幕上的图标或按钮,weditor界面右侧的Coding框会同步展现元素操作的代码,同时手机界面也会相应同步切换页面。
感谢
部分内容参考以下:
https://www.cnblogs.com/fnng/p/8486863.html
https://testerhome.com/topics/11357
https://blog.csdn.net/Master724/article/details/107962349?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163394586216780265448858%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=163394586216780265448858&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-2-107962349.pc_search_ecpm_flag&utm_term=uiautomator2&spm=1018.2226.3001.4187
- 上一篇:开始第一个Flet应用
- 下一篇:论文写作指导与框架建议
相关推荐
- 团队管理“布阵术”:3招让你的团队战斗力爆表!
-
为何古代军队能够以一当十?为何现代企业有的团队高效似“特种部队”,有的却松散若“游击队”?**答案正隐匿于“布阵术”之中!**今时今日,让我们从古代兵法里萃取3个核心要义,助您塑造一支战斗力爆棚的...
- 知情人士回应字节大模型团队架构调整
-
【知情人士回应字节大模型团队架构调整】财联社2月21日电,针对原谷歌DeepMind副总裁吴永辉加入字节跳动后引发的团队调整问题,知情人士回应称:吴永辉博士主要负责AI基础研究探索工作,偏基础研究;A...
- 豆包大模型团队开源RLHF框架,训练吞吐量最高提升20倍
-
强化学习(RL)对大模型复杂推理能力提升有关键作用,但其复杂的计算流程对训练和部署也带来了巨大挑战。近日,字节跳动豆包大模型团队与香港大学联合提出HybridFlow。这是一个灵活高效的RL/RL...
- 创业团队如何设计股权架构及分配(创业团队如何设计股权架构及分配方案)
-
创业团队的股权架构设计,决定了公司在随后发展中呈现出的股权布局。如果最初的股权架构就存在先天不足,公司就很难顺利、稳定地成长起来。因此,创业之初,对股权设计应慎之又慎,避免留下巨大隐患和风险。两个人如...
- 消息称吴永辉入职后引发字节大模型团队架构大调整
-
2月21日,有消息称前谷歌大佬吴永辉加入字节跳动,并担任大模型团队Seed基础研究负责人后,引发了字节跳动大模型团队架构大调整。多名原本向朱文佳汇报的算法和技术负责人开始转向吴永辉汇报。简单来说,就是...
- 31页组织效能提升模型,经营管理团队搭建框架与权责定位
-
分享职场干货,提升能力!为职场精英打造个人知识体系,升职加薪!31页组织效能提升模型如何拿到分享的源文件:请您关注本头条号,然后私信本头条号“文米”2个字,按照操作流程,专人负责发送源文件给您。...
- 异形柱结构(异形柱结构技术规程)
-
下列关于混凝土异形柱结构设计的说法,其中何项正确?(A)混凝土异形柱框架结构可用于所有非抗震和抗震设防地区的一般居住建筑。(B)抗震设防烈度为6度时,对标准设防类(丙类)采用异形柱结构的建筑可不进行地...
- 职场干货:金字塔原理(金字塔原理实战篇)
-
金字塔原理的适用范围:金字塔原理适用于所有需要构建清晰逻辑框架的文章。第一篇:表达的逻辑。如何利用金字塔原理构建基本的金字塔结构受众(包括读者、听众、观众或学员)最容易理解的顺序:先了解主要的、抽象的...
- 底部剪力法(底部剪力法的基本原理)
-
某四层钢筋混凝土框架结构,计算简图如图1所示。抗震设防类别为丙类,抗震设防烈度为8度(0.2g),Ⅱ类场地,设计地震分组为第一组,第一自振周期T1=0.55s。一至四层的楼层侧向刚度依次为:K1=1...
- 结构等效重力荷载代表值(等效重力荷载系数)
-
某五层钢筋混凝土框架结构办公楼,房屋高度25.45m。抗震设防烈度8度,设防类别丙类,设计基本地震加速度0.2g,设计地震分组第二组,场地类别为Ⅱ类,混凝土强度等级C30。该结构平面和竖向均规则。假定...
- 体系结构已成昭告后世善莫大焉(体系构架是什么意思)
-
实践先行也理论已初步完成框架结构留余后人后世子孙俗话说前人栽树后人乘凉在夏商周大明大清民国共和前人栽树下吾之辈已完成结构体系又俗话说青出于蓝而胜于蓝各个时期任务不同吾辈探索框架结构体系经历有限肯定发展...
- 框架柱抗震构造要求(框架柱抗震设计)
-
某现浇钢筋混凝土框架-剪力墙结构高层办公楼,抗震设防烈度为8度(0.2g),场地类别为Ⅱ类,抗震等级:框架二级,剪力墙一级,混凝土强度等级:框架柱及剪力墙C50,框架梁及楼板C35,纵向钢筋及箍筋均采...
- 梁的刚度、挠度控制(钢梁挠度过大会引起什么原因)
-
某办公楼为现浇钢筋混凝土框架结构,r0=1.0,混凝土强度等级C35,纵向钢筋采用HRB400,箍筋采用HPB300。其二层(中间楼层)的局部平面图和次梁L-1的计算简图如图1~3(Z)所示,其中,K...
- 死要面子!有钱做大玻璃窗,却没有钱做“柱和梁”,不怕房塌吗?
-
活久见,有钱做2层落地大玻璃窗,却没有钱做“柱子和圈梁”,这样的农村自建房,安全吗?最近刷到个魔幻施工现场,如下图,这栋5开间的农村自建房,居然做了2个全景落地窗仔细观察,这2个落地窗还是飘窗,为了追...
- 不是承重墙,物业也不让拆?话说装修就一定要拆墙才行么
-
最近发现好多朋友装修时总想拆墙“爆改”空间,别以为只要避开承重墙就能随便砸!我家楼上邻居去年装修,拆了阳台矮墙想扩客厅,结果物业直接上门叫停。后来才知道,这种配重墙拆了会让阳台承重失衡,整栋楼都可能变...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- MVC框架 (46)
- spring框架 (46)
- 框架图 (58)
- bootstrap框架 (43)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- laravel框架 (46)
- express框架 (43)
- scrapy框架 (52)
- beego框架 (42)
- java框架spring (43)
- grpc框架 (55)
- 前端框架bootstrap (42)
- orm框架有哪些 (43)
- ppt框架 (48)
- 内联框架 (52)
- winform框架 (46)
- gui框架 (44)
- cad怎么画框架 (58)
- ps怎么画框架 (47)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)
- oracle提交事务 (47)