盘锦网站变建设,网站建设成立领导小组,网站按照谁建设 谁负责,表情包制作app1.说明
我们之前在电脑操作手机进行自动化测试#xff0c;基本上都是通过Appium的#xff0c;这个工具确实强大#xff0c;搭配谷歌官方的UiAutomator基本上可以完成各种测试#xff0c;但缺点也很明显#xff0c;配置环境太麻烦了#xff0c;需要jdk、sdk等#xff0c…1.说明
我们之前在电脑操作手机进行自动化测试基本上都是通过Appium的这个工具确实强大搭配谷歌官方的UiAutomator基本上可以完成各种测试但缺点也很明显配置环境太麻烦了需要jdk、sdk等后来有人在UiAutomator的基础上使用http请求rpc服务的方式做了一个uiautomator但这个项目很久没有维护了后面有人在此基础上进行重构和精简所以又有了uiautomator2这是目前为止比较好用的Python操作手机的测试库之一
2.安装环境
2.1 安装uiautomator2
使用uiautomator2的要求是Android版本 4.4或以上版本Python 3.6或以上版本社区反馈3.8.0不支持, 但是3.8.2支持
pip install uiautomator22.2 安装weditor
uiautomator2是控制手机的 还需要一个查看手机元素的库与uiautomator2配套的是weditor。
注意如果你安装0.6.5或以上版本的weditor可能会遇到编码错误 UnicodeDecodeError: ‘gbk’ codec can’t decode byte 0xad in position 825: illegal multibyte sequence。所以你可以选择0.6.4版本
pip install weditor0.6.4或者可以把Python环境的默认编码改成utf-8在cmd执行
set PYTHONUTF812.3 安装adb
adb的作用是连接安卓设备比如说查看当前已连接上电脑的设备我们可以在android官网下载platform-tools里面包含了adb程序下载之后无需安装进行解压就能用要是觉得不方便使用的话你可以把adb.exe添加到系统环境变量
https://developer.android.com/studio/releases/platform-tools3.初始化
首先使用adb查看你的手机是否已连接上电脑需要打开开发者选项会显示设备序列号
adb.exe devices之后初始化uiautomator2 它会在你的手机上安装一个叫做atx-agent的应用
uiautomator2 init我这里使用的是模拟器大概结果如下图初始化成功的话后面会有Successfully init AdbDevice(serialXXX)的提示
4.uiautomator2连接设备
通过USB连接
import uiautomator2 as u2d u2.connect(emulator-5554) # emulator-5554就是在adb devices显示的序列号
print(d.info)通过WiFi连接确保手机与电脑处于同一个局域网并且能ping同手机
import uiautomator2 as u2
d u2.connect(192.168.0.100)通过adbWiFi连接
import uiautomator2 as u2d u2.connect_adb_wifi(192.168.0.101:5555)5.weditor定位元素
现在已经可以通过uiautomator2操作手机了如果想要定位元素的话刚刚安装好的weditor就可以派上用场了在cmd输入weditor它会自动打开浏览器
weditor我们在打开的网页上面输入设备号或者ip点击“Connect”如果“Connect”按钮出现一个绿色的树叶图标说明已经连接上。再往右一点有一个“Dump hierarchy”按钮点击一下就刷新页面了你也可以打开“实时”选项这样它会一直刷新页面。下面的窗口会显示当前手机的页面点击一下某个控件就能显示它的信息右边还有一个写测试代码的窗口虽然我们一般都是通过Python控制但Python端每次运行都需要花费时间可以先在网页端测试一下定位是否准确
6.操作APP
6.1 查看APP包名
对于操作APP基本上都是通过包名和activity控制的比如说打开关闭、安装卸载等操作所以获取包名是第一步你可以通过weditor查看某个应用的包名也可以通过uiautomator2获取
import uiautomator2 as u2d u2.connect(emulator-5554)# 获取所有包名返回一个列表
all_pkg_list d.app_list()
print(len(all_pkg_list), all_pkg_list)# 获取正在运行的APP的包名
running_pkg_list d.app_list_running()
print(len(running_pkg_list), running_pkg_list)6.2 获取包信息
info d.app_info(com.android.settings)
print(info)
# 获取到的信息如下
# {packageName: com.android.settings, mainActivity: Settings, label: Settings, versionName: 9, versionCode: 28, size: 49083357}6.3 启动停止APP
# 直接启动APP若wait设置为True则一直等到启动结束
d.app_start(com.android.settings, waitTrue)# 等待APP启动结束默认20秒超时启动后 返回pid如果启动失败则pid为0
pid d.app_wait(com.android.settings, timeout20)
print(pid)# 停止APP
d.app_stop(com.android.settings)
# 停止所有APPexcludes参数可以指定哪些APP不停止
d.app_stop_all(excludes[com.android.browser, com.android.bluetooth])6.4 安装卸载APP
# 安装APP参数可以是本地文件也可以是url
d.app_install(rC:\Users\admin\Desktop\IcyFtpServer_v1.0.apk)# 卸载APP
d.app_uninstall(com.ice.icyftpserver)
# 卸载所有APPexcludes参数指定要保留的APP
# d.app_uninstall_all(excludes[app_uninstall_all])
7.操作元素
当打开APP之后我们就可以操作APP了包括定位元素点击、长按等操作
7.1 选择器
定位元素很重要只有获取到某个元素才可以操作。定位元素的方式有多种比如说index、resourceId、className、text、textContains等其中比较准确的是通过index和resourceId进行定位速度很快index、resourceId和className的值都可以在weditor看到。text是指元素的全部文本textContains是指包含部分文本textStartsWith是指以某文本开始这几种选择器都会搜索页面所以速度会比较慢
# 通过index定位
d(index1).click()# 通过资源id定位
d(resourceIdcom.android.settings:id/search_action_bar_title).click()# 通过该className定位
d(classNameandroid.widget.TextView).click()# 通过文本定位速度比较慢
d(text在设置中搜索).click()
# 包含XXX文本
d(textContains在设置中搜索).click()
# 以XXX开始的文本
d(textStartsWith在设置中).click()
我们注意到除了index和resourceId可以准确定位到唯一的元素其他选择器都可能定位到多个元素为了提高准确率我们可以同时使用多个选择器
# 同时使用多个选择器提供准确率
d(classNameandroid.widget.TextView, textContains在设置中).click()谷歌官网给出的选择还有很多感兴趣的话可以看一下 https://developer.android.com/reference/android/support/test/uiautomator/UiSelector
选择选择器返回的是一个UiObject对象但要注意即使没有定位到它也不会报错直到你进行点击等操作的时候才会超时报错
UiObject可以同时包含多个元素即它是一个容器因此我们可以查看该对象包含多少个元素并且可以通过遍历的方式依次访问选中的元素
selected_el d(resourceIdcom.android.settings:id/search_action_bar_title)
# 查看元素的格式
print(selected_el.count)
print(len(selected_el))# 访问元素
print(selected_el[0])
for el in selected_el:print(el)# 只要第一个元素
selected_el d(classNameandroid.widget.TextView, instance0)
print(len(selected_el))另外也可以通过当前选择的元素选择子元素或者兄弟元素目前不支持选择父元素
# 通过child()选择子元素
d(classNameandroid.widget.LinearLayout).child(text网络和互联网)
# 通过sibling()选择兄弟元素
d(classNameandroid.widget.LinearLayout).sibling(classNameandroid.widget.ImageView)# 选择上面的元素
d(resourceIdandroid:id/title).up()
# 选择下面的元素
d(resourceIdandroid:id/title).down()
# 选择左边的元素
d(resourceIdandroid:id/title).left()
# 选择右边的元素
d(resourceIdandroid:id/title).right()7.2 元素信息
通过选择器定位元素之后可以调用一下exists属性看是否真的存在如果存在再进行其他操作如果想知道元素的边界、中心点的位置也是可以获取到的
selected_el d(resourceIdcom.android.settings:id/search_action_bar_title)
# 判断元素是否存在
if selected_el.exists:# 元素的信息与在weditor上看到的基于一致print(info:, selected_el.info)# 元素边界左上点和右下点的x、yprint(selected_el.bounds())# 元素的中心位置print(selected_el.center())# 元素个数即len(selected_el)print(selected_el.count)7.3 点击和长按
一般来说获取到元素之后再进行点击或者长按操作
selected_el d(resourceIdcom.android.settings:id/search_action_bar_title)
# 点击元素timeout是等待元素出现超时时间offset是点击位置的偏移量
selected_el.click(timeoutNone, offsetNone)
# 长按元素duration长按事件默认是0.5秒timeout是等待元素出现的超时时间
selected_el.long_click(duration0.5, timeoutNone)
# 一直点击直到元素小时maxretry是最大点击次数默认是10interval是每次点击间隔默认是1秒
selected_el.click_gone(maxretry10, interval1.0)如果你不想通过定位到的元素进行点击而是通过指定的x、y位置也是可以的
x, y 384.0, 191.5
# 点击
d.click(x, y)
# 长按
d.long_click(x, y, duration0.5)
# 双击
d.double_click(x, y, duration0.1)7.4 设置和清除文本
除了点击还经常需要在文本框输入文本或者清除文本或者获取文本的内容
d.app_start(com.android.settings, waitTrue)
d(resourceIdcom.android.settings:id/search_action_bar_title).click()
selected_el d(resourceIdandroid:id/search_src_text)
# 设置文本
selected_el.set_text(wifi)
# 获取文本
print(selected_el.get_text())
# 清除文本
selected_el.clear_text()
print(selected_el.get_text())
7.5 滑动操作
可以调用swipe()方法进行滑动支持上下左右四个方向它需要两个参数direction是方向支持up、down、left、rightsteps是长度默认值是10一步大概5毫秒
d(resourceIdcom.android.settings:id/main_content).swipe(directionup, steps10)基于时间的滚动感觉不是很好控制所以还可以调用swipe_ext()方法控制滑动比例比如说向上滑动80%的距离
d.swipe_ext(up, scale0.8)8.屏幕操作
8.1 屏幕分辨率
d.info可以获取到屏幕分辨率和物理分辨率也调用window_size()方法直接返回屏幕分辨率
print(d.info)
print(d.window_size())8.2 截屏
如果看到一个漂亮的界面可以选择截个图。可以调用screenshot()方法截图第一个参数是图片保存的路径第二个参数是处理图片的库默认是pillow也支持opencv如果你没有安装pillow或opencv那就指定第二个参数为raw
# 使用pillow
d.screenshot(./test.jpg)# 使用opencv
import cv2
image d.screenshot(formatopencv)
cv2.imwrite(home.jpg, image)# 直接保存源数据
img d.screenshot(formatraw)
with open(test.jpg, wb) as f:f.write(img)8.3 息屏亮屏
我们可以锁屏和亮屏可以在info信息里面找到当前是息屏还是亮屏
# 亮屏
d.screen_on()
# 屏幕状态
print(d.info.get(screenOn)) # True
# 锁屏
d.screen_off()
print(d.info.get(screenOn)) # False# 解锁屏幕实际过程是先按下power键再滑动屏幕
d.unlock()8.4 自动旋转屏幕
# 设置屏幕反向
d.set_orientation(left)
time.sleep(2)
d.set_orientation(right)
time.sleep(2)
d.set_orientation(natural)
time.sleep(2)
# 自动旋转屏幕
d.freeze_rotation(True)
9.按键事件
目前uiautomation2支持的按键还不是很多大概有home, back, left, right, up, down, center, menu, search, enter, delete(or del), recent(recent apps), volume_up, volume_down, volume_mute, camera, power.
d.press(home) # 主页键
d.press(recent) # 近期任务键
d.press(back) # 返回键
d.press(power) # 电源键
d.press(menu) # 菜单键
d.press(volume_up) # 音量键
d.press(volume_down) # 音量-键
d.press(volume_mute) # 静音键除了上面的press某些按键之外也可以调出键盘然后发送按键。不过如果是输入框输入文本还是建议使用set_text()更方便
# 依次键入a、b、c、d、e、f、g键
d(resourceIdandroid:id/search_src_text).send_keys(abcdefg)
# 直接把输入框文本设置成abcdefg
d(resourceIdandroid:id/search_src_text).set_text(abcdefg)10.上传下载文件
有时候需要把电脑端的文件上传到手机端或者从手机端下载到电脑端。不过一定要注意存储位置一定要存在并且有读写权限
# 上传到手机端
d.push(rC:\Users\admin\Desktop\test.txt, /storage/emulated/0/)
# 从手机端下载
d.pull(/storage/emulated/0/test.txt, test2.txt)11.执行shell命令
如果uiautomator2的操作都不能满足你的需求你也可以直接通过adb执行原生shell命令支持传参
# 调用shell命令执行成功时返回码是0
output, exit_code d.shell(pwd, timeout60)
print(output, exit_code)# 当stream为True则只返回Response对象
output d.shell(pwd, streamTrue)
print(output.text)# 如果该命令有参数可以使用列表的方式
output, exit_code d.shell([ls, -l])
print(output, exit_code)