UIautomator2使用文档
目录
一、安装
1、uiautomator2介绍
2、uiautomator2安装
3、安装设备守护进程
4、安装weditor
二、使用指南
1、连接设备
一、安装
1、uiautomator2介绍
UiAutomator是Google提供的安卓自动化测试Java库,功能很强,但测试脚本只能使用Java语言,脚本要打包成jar或者apk包上传到设备上才能运行。
感谢 Xiaocong He (@xiaocong),他用Python编写了uiautomator,原理是在手机上运行了一个http rpc服务,将uiautomator中的功能开放出来,然后再将这些http接口封装成Python库。因为xiaocong/uiautomator已经很久不更新。所以我们直接fork了一个版本,命名为uiautomator2,对原有的库的bug进行了修复,还增加了很多新的Feature。主要有以下部分:
设备和测试电脑可以脱离数据线,通过WiFi互联(基于atx-agent)
集成openstf/minicap达到实时屏幕投频,以及实时截图
集成openstf/minitouch达到精确实时控制设备
修复xiaocong/uiautomator经常性退出的问题
代码进行了重构和精简,方便维护
实现了一个设备管理平台(也支持iOS) atxserver2
这里要先说明下,因为经常有很多人问 openatx/uiautomator2 并不支持iOS测试,需要iOS自动化测试,可以转到这个库 openatx/facebook-wda。
PS: 这个库 https://github.com/NeteaseGame/ATX 目前已经不维护了。
Android Uiautomator2 Python Wrapper 这是一个可以完成Android的UI自动化的python库
2、uiautomator2安装
#第一种pip安装开发版需要使用–pre
pip install --pre uiautomator2
#第二种源代码安装
git clone https://github.com/openatx/uiautomator2
pip install -e uiautomator2
#咱们需要截屏所以有需要使用pillow库
pip install pillow
#源代码中有个 psutil库,python3.6安装这个库需要使用5.7.0版本,装5.8.0会报错,捯饬了半个多小时。。。
pip install psutil==5.7.0
3、安装设备守护进程
#配置好adb环境,配置好环境变量,初始化手机,指南,安装提示success即可
python -m uiautomator2 init
#安装自动化ui定位weditor,自动安装本库所需的设备端程序:uiautomator-server ,atx-agent ,openstf / minicap ,openstf / minitouch 也可单独下载安装
4、安装weditor
#目前最新的稳定版为 0.1.0
pip install -U weditor
#启动weditor
python -m weditor
#Windows系统可以使用命令在桌面创建一个快捷方式 python -m weditor --shortcut
命令行启动 python -m weditor 会自动打开浏览器,输入设备的ip或者序列号,点击Connect即可。
输入命令:adb devices,device前面的就是序列号
List of devices attached
866b7d2b device
二、使用指南
1、连接设备
连接3种方法:
#通过WiFi,比如wifi是1.0.0.0.1
#需要电脑和手机处于同一网络中
import uiautomator2 as u2
d = u2.connect("1.0.0.0.1")
print(d.info)
#通过USB,输入设备编码即可
import uiautomator2 as u2
d = u2.connect("123ff45ff")
print(d.info)
#默认自动设备链接
import uiautomator2 as u2
d = u2.connect()#connect()置空就会自动识别
print(d.info)
#注:当连接多个设备的时候不能进行多线程执行,只能等一个设备执行完成后,在执行另一个设备
2、API手册
1、全局设定
#设置每次点击UI后再次单击之间延迟1.5秒
d.click_post_delay = 1.5
#设置默认元素等待超时(秒)
d.wait_timeout = 20.
2、设备信息
d.info
#得出设备链接信息
print(d.window_size())
#获取屏幕大小
print(d.current_app())
#获取当前应用的信息
print(d.serial)
#获取设备序列号
print(d.wlan_ip)
#获取WIFI IP
print(d.device_info)
#获取详细的设备信息
3、屏幕和键盘操作
#打开/关闭屏幕
d.screen_on()
#开启屏幕
d.screen_off()
#关闭屏幕
d.info.get("screen")
#获取屏幕开/关状态
#android>=4.4
d.press("home")
#按下home键
d.press("back")
#按下back键
d.press(0*07,0*02)
#按下编码
'''支持按键模式'''
home
#主页按钮
back
#返回
left
#左
right
#右
up
#上
down
#下
center
#回车
menu
#菜单
search
#搜索
enter
#输入
delete ( or del)
#删除
recent (recent apps)
#打开最近项目
volume_up
#音量+
volume_down
#音量—
volume_mute
#静音
camera
#相机
power
#电源键
4、手势操作
d.unlock()
#结锁屏幕
d.click(X,Y)
#点击屏幕坐标
d.long_click(x,y)
#长按屏幕
d.long_click(x,y,1)
#长按屏幕1s,默认是0.5,可自行配置
d.swipe(sx, sy, ex, ey)
#根据坐标滑动
d.swipe(sx, sy, ex, ey,1)
#根据坐标滑动,1代表滑动速度,默认0.5
d.drag(sx, sy, ex, ey)
#根据坐标拖动,适用于结算和滑块处理
d.drag(sx, sy, ex, ey, 1)
#根据坐标拖动,拖动时长1s,默认0.5
5、屏幕操作
#截图
d.screenshot('1.jpg')
#截图保存在本地,文件名为1.jpg
#想获取其他格式的需要安装 pillow、numpy和cv2等库,具体不累述
d.open_notification()
#打开通知
d.open_quick_settings()
#打开快速设置
d.freeze_rotation()
# 冻结旋转
d.freeze_rotation(False)
# 开启旋转
'''检查特定的UI对象是否存在'''
d(text="Settings").exists
# 返回布尔值,如果存在则为True,否则为False
d.exists(text="Settings")
# 另一种写法
# 高级用法
d(text="Settings").exists(timeout=3)
# 等待'Settings'在3秒钟出现
d(text="Settings").info
# 获取特定UI对象的信息
'''获取/设置/清除可编辑字段的文本(例如EditText小部件)'''
d(text="Settings").get_text()
#得到文本小部件
d(text="Settings").set_text("My text...")
#设置文本
d(text="Settings").clear_text()
#清除文本
d(text="Settings").center()
# 获取Widget中心点
#d(text="Settings").center(offset=(0, 0)) # 基准位置左前
6、文件操作
d.push('1.txt','sdcard/downloacd')
#推送到文件下
d.push('1.txt','sdcard/downloacd/2.txt')
#推送并重命名到文件夹下
with open("foo.txt", 'rb') as f:
d.push(f, "/sdcard/")
#push fileobj
d.push("1.sh", "/data/local/tmp/", mode=0o755)
#推送并修改文件模式,在Python中表示八进制的友好方法默认0o755,文件权限设置
d.pull("/sdcard/1.txt", "1.txt")
#从设备侧拉取文件
7、定位方法及常用方法
'''定位方法'''
#text定位单击
d(text="Settings").click()
d(text="Settings", className="android.widget.TextView").click()
#resourceId定位单击
d(resourceId="com.ruguoapp.jike:id/tv_title", className="android.widget.TextView").click()
#description定位单击
d(description="确定").click()
d(description="确定", className="android.widget.TextView").click()
#className定位单击
d(className="android.widget.TextView").click()
#xpath定位单击
d.xpath("//android.widget.FrameLayout[@index='0']/android.widget.LinearLayout[@index='0']").click()
#坐标单击
d.click(182, 1264)
'''常用方法'''
# 等待10s
d.xpath("//android.widget.TextView").wait(10.0)
# 找到并单击
d.xpath("//*[@content-desc='分享']").click()
# 检查是否存在
if d.xpath("//android.widget.TextView[contains(@text, 'Se')]").exists:
print("exists")
# 获取所有文本视图文本、属性和中心点
for elem in d.xpath("//android.widget.TextView").all():
print("Text:", elem.text)
#获取视图文本
for elem in d.xpath("//android.widget.TextView").all():
print("Attrib:", elem.attrib)
#获取属性和中心点
#返回: (100, 200)
for elem in d.xpath("//android.widget.TextView").all():
print("Position:", elem.center())
'''xpath常见用法'''
# 所有元素
//*
# resource-id包含login字符
//*[contains(@resource-id, 'login')]
# 按钮包含账号或帐号
//android.widget.Button[contains(@text, '账号') or contains(@text, '帐号')]
# 所有ImageView中的第二个
(//android.widget.ImageView)[2]
# 所有ImageView中的最后一个
(//android.widget.ImageView)[last()]
# className包含ImageView
//*[contains(name(), "ImageView")]
# 等待10s
d.xpath("//android.widget.TextView").wait(10.0)
# 找到并单击
d.xpath("//*[@content-desc='分享']").click()
# 检查是否存在
if d.xpath("//android.widget.TextView[contains(@text, 'Se')]").exists:
print("exists")
# 获取所有文本视图文本、属性和中心点
for elem in d.xpath("//android.widget.TextView").all():
print("Text:", elem.text)
#获取视图文本
for elem in d.xpath("//android.widget.TextView").all():
print("Attrib:", elem.attrib)
#获取属性和中心点
#返回: (100, 200)
for elem in d.xpath("//android.widget.TextView").all():
print("Position:", elem.center())