不写一行代码实现mobile自动化

2021-04-02 11:26:36 浏览数 (1)

我们写移动自动化的时候,一般用appium, 感觉appium用起来太重了。 首先装环境得搞半天,然后启动一个driver要填很多参数,一个参数没填,或者填错了,就启动不起来。 如果是小白,遇到各种坑。好不容易跑起来了,写了一通代码,结果项目迭代了,又得重写。 有没有一种轻量的,可以录制的工具可以用呢? python-uiautomator2 自动化测试开源工具,其封装了谷歌自带的 uiautomator2 测试框架,可以运行在支持 Python 的任一系统上。

工作原理:

python-uiautomator2 主要分为两个部分,python 客户端,移动设备

python 端: 运行脚本,并向移动设备发送 HTTP 请求; 移动设备:移动设备上运行了封装了 uiautomator2 的 HTTP 服务,解析收到的请求,并转化成 uiautomator2 的代码; 整个过程:

在移动设备上安装 atx-agent(守护进程),随后 atx-agent 启动 uiautomator2 服务(默认 7912 端口)进行监听; 在 PC 上编写测试脚本并执行(相当于发送 HTTP 请求到移动设备的 server 端); 移动设备通过 WIFI 或 USB 接收到 PC 上发来的 HTTP 请求,执行制定的操作。

安装:
代码语言:javascript复制
pip install -U uiautomator2

如果这行代码跑成功说明环境好了

代码语言:javascript复制
import uiautomator2 as u2
# 连接并启动
d = u2.connect() 
print(d.info)

注意:需要安装 adb 工具,并配置到系统环境变量,才能操作手机。这个比起appium,是不是简单多了。

安装 weditor

weditor 是一款基于浏览器的 UI 查看器,用来帮助我们查看 UI 元素定位。类似appium desktop, 不知道现在appium是否也支持录制了。

使用 pip 安装

代码语言:javascript复制
pip install -U weditor

启动运行weditor

代码语言:javascript复制
python -m weditor
#或者直接在命令行运行
weditor

就可以看到如下界面:

将手机的alias填入,然后connect, 实时开关打开。就可以录制了。

这个工具很方便定位元素,可以看到元素的

录制完成后,还可以在里面执行。直接就能看到效果。

支持的元素定位方式:

代码语言:javascript复制
text    text 是指定文本的元素
textContains    text 中包含有指定文本的元素
textMatches text 符合指定正则的元素
textStartsWith  text 以指定文本开头的元素
className   className 是指定类名的元素
classNameMatches    className 类名符合指定正则的元素
description description 是指定文本的元素
descriptionContains description 中包含有指定文本的元素
descriptionMatches  description 符合指定正则的元素
descriptionStartsWith   description 以指定文本开头的元素
checkable   可检查的元素,参数为 True,False
checked 已选中的元素,通常用于复选框,参数为 True,False
clickable   可点击的元素,参数为 True,False
longClickable   可长按的元素,参数为 True,False
scrollable  可滚动的元素,参数为 True,False
enabled 已激活的元素,参数为 True,False
focusable   可聚焦的元素,参数为 True,False
focused 获得了焦点的元素,参数为 True,False
selected    当前选中的元素,参数为 True,False
packageName packageName 为指定包名的元素
packageNameMatches  packageName 为符合正则的元素
resourceId  resourceId 为指定内容的元素
resourceIdMatches   resourceId 为符合指定正则的元素
元素常用 API

表格标注有 @property 装饰的类属性方法,均为下方示例方式

代码语言:javascript复制
d(test="Settings").exists
方法  描述  返回值 备注
exists()    判断元素是否存在    True,Flase  @property
info()  返回元素的所有信息   字典  @property
get_text()  返回元素文本 字符串      
set_text(text)  设置元素文本 None     
clear_text()    清空元素文本 None     
center()    返回元素的中心点位置  (x,y)   基于整个屏幕的点
设备交互

单击

代码语言:javascript复制
d(text='Settings').click()
#单击直到元素消失 , 超时时间 10,点击间隔 1
d(text='Settings').click_gone(maxretry=10, interval=1.0)

长按

代码语言:javascript复制
d(text='Settings').long_click()

拖动

代码语言:javascript复制
# 在 0.25S 内将 Setting 拖动至 Clock 上,拖动元素的中心位置
# duration 默认为 0.5, 实际拖动的时间会比设置的要高
d(text="Settings").drag_to(text="Clock", duration=0.25)

# 拖动 settings 到屏幕的某个点上
d(text="Settings").drag_to(877,733, duration=0.25)

#两个点之间的拖动 , 从点 1 拖动至点 2
d.drag(x1,y1,x2,y2)

滑动 滑动有两个,一个是在 driver 上操作,一个是在元素上操作

代码语言:javascript复制
从元素的中心向元素边缘滑动

# 在 Setings 上向上滑动。steps 默认为 10
# 1 步约为 5 毫秒,因此 20 步约为 0.1 s
d(text="Settings").swipe("up", steps=20) 

driver 上操作
即对整个屏幕操作

# 实现下滑操作
x,y = d.window_size()
x1 = x / 2
y1 = y * 0.1
y2 = y * 0.9
d.swipe(x1,y1,x1,y2)

driver 滑动的扩展方法,可以直接实现滑动,不需要再自己封装定位点

# 支持前后左右的滑动
# "left", "right", "up", "down"
# 下滑操作
d.swipe_ext("down")

等待元素出现或者消失

代码语言:javascript复制
# 等待元素出现
d(text="Settings").wait(timeout=3.0)
# 等待元素消失,返回 True False,timout 默认为全局设置的等待时间
d(text='Settings').wait_gone(timeout=20)

滚动界面 设置 scrollable 属性为 True;

滚动类型:horiz 为水平,vert 为垂直;

滚动方向:

forward 向前 backward 向后 toBeginning 滚动至开始 toEnd 滚动至最后 to 滚动直接某个元素出现 所有方法均返回 Bool 值;

代码语言:javascript复制
# 垂直滚动到页面顶部 / 横向滚动到最左侧
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")
Take screenshot of widget

im = d(text="Settings").screenshot()
im.save("settings.jpg")

toast 操作

代码语言:javascript复制
# 获取 toast, 当没有找到 toast 消息时,返回 default 内容
d.toast.get_message(timout=5,default='no toast')
# 清空 toast 缓存
d.toast.reset()
监控界面

使用 wather 进行界面的监控,可以用来实现跳过测试过程中的弹框

当启动 wather 时,会新建一个线程进行监控

可以添加多个 watcher

用法

代码语言:javascript复制
# 注册监控 , 当界面内出现有 allow 字样时,点击 allow
d.watcher.when('allow').click()

# 移除 allow 的监控
d.watcher.remove("allow")

# 移除所有的监控
d.watcher.remove()

# 开始后台监控
d.watcher.start()
d.watcher.start(2.0) # 默认监控间隔 2.0s

# 强制运行所有监控
d.watcher.run()

# 停止监控
d.watcher.stop()

# 停止并移除所有的监控,常用于初始化
d.watcher.reset()

2.11.0 版本 新增了一个 watch_context 方法 , 写法相比 watcher 更简洁,官方推荐使用此方法来实现监控,目前只支持 click() 这一种方法。

代码语言:javascript复制
wct = d.watch_context()
# 监控 ALLOW
wct.when("ALLOW").click()
# 监控 OK
wct.when('OK').click()
 # 开启弹窗监控,并等待界面稳定(两个弹窗检查周期内没有弹窗代表稳定)
wct.wait_stable()

#其它实现代码
# 停止监控
wct.stop()

屏幕方向

代码语言:javascript复制
# 设置屏幕方向
d.set_orientation(value)
# 获取当前屏幕方向
d.orientation

方法真的好多,这里就不列举了,基本上移动测试的基本方法都会有,如果不知道,写代码的时智能提示就可以找到了。或者自己去熟悉这个开源的框架。 这个工具个人是觉得很好用的,特别是toast, 以及监视器,对处理弹框子,真是太好不过了。

将录制好的代码,结构化一下,然后用pytest,或者unittest组织一下。就可以得到一个高效且方便的自动化测试了。

这篇只是写了android的,其实IOS也差不多,关键是要编译安装wda.

0 人点赞