目录
weditor报错Local server not started, start with
UiAutomator是Google提供的安卓自动化测试Java库,功能很强,但测试脚本只能使用Java语言,uiautomator2是uiautomator的升级版,uiautomator2将uiautomator中的接口封装成了Python库,因此它支持的语言为Python。
场景:我是Windows10系统,我的需求是在远程桌面的机器能测试安卓手机上的应用,在能与安卓手机直连的物理机上和远程桌面的机器上都安装上ADB,安卓手机和物理机以及远程机器都是在一个局域网内,如果你是直接物理机测试,那么以下对远程机器做的操作都放到你的物理机上做
官方文档要求:
- Android版本 4.4+
- Python 3.8+
环境搭建
python安装
1. 安装python环境,安装在远程机器上,我安装python版本为python3.8
2. 等待安装完成之后,打开cmd窗口输入python回车,出现以下界面表示安装成功
ADB安装
在物理机和远程桌面的机器上都安装上ADB(如果你只是使用物理机测试,那就只安装在物理机)
Windows版本:https://dl.google.com/android/repository/platform-tools-latest-windows.zip
Mac版本:https://dl.google.com/android/repository/platform-tools-latest-windows.zip
Linux版本:https://dl.google.com/android/repository/platform-tools-latest-linux.zip
1. 下载ADB 解压之后把解压路径放到系统变量(path)里面去
2. 命令行窗口输入adb,出现以下信息说明安装成功
开始手机连接
1. 安卓手机进入开发者模式,我的手机是在关于手机里面连续点击版本号七次就能进入开发者模式了
2. 点进安卓手机的开发人员选项,打开以下选项
3. 将手机和物理机直连,如果有弹出选项的话则选择仅充电
4. 打开物理机的cmd窗口,输入adb devices命令
5. 输入以上命令回车之后,手机会弹出以下窗口, 点击确定(如果已经和物理机连接上了,但是一直没有这个窗口弹出,可以重启一下手机再试)
6. 再次输入adb devices 就会发现已经连接
7. 输入adb tcpip 5555 该命令是启动手机的网络调试,端口号是5555(你也可以用别的端口号)
8. 接下来就可以使用安卓手机IP地址+端口号直接进行无线连接了,以管理员方式运行远程机器的cmd窗口(要以管理员方式运行,否则可能连不上),输入adb connect ip:端口号
我的手机ip是192.168.8.155 端口号是5555,所以我执行以下命令连接,出现already connected 表示连接成功
安装python的uiautomator2库
1. 在远程机器的cmd窗口执行以下命令
pip install -U uiautomator2
安装atx-agent
1. 在远程机器的cmd窗口运行以下命令安装包含httprpc服务的apk到手机
python -m uiautomator2 init
2. 命令执行成功以后会发现手机安装以下软件
安装weditor
1. 在远程机器的命令行窗口执行以下命令
pip install -U weditor
由于我直接安装出错了,所以加了个版本号安装的是0.5.2版本
2. 在命令行输入 weditor 会自动打开浏览器,在页面上输入模拟器的设备序列号,点击Connect,然后点击Dump Hierarchy刷新,可以看到模拟器的界面,如果连接不上可能是ATX没有启动,在手机打开ATX,点击启动UIAUTOMATOR
设备序列号就是下面红色框内的,自己在远程机器上输入adb devices查看
刷新之后转圈时间过久的问题
1.打开设置->电池->找到ATX应用 关闭省电的措施项,再刷新就会发现不再持久转圈了
开始测试
以下操作我都是在远程机器上进行的
需求:以百度贴吧为例子,我想要做的是通过代码打开百度贴吧app,点击搜索按键并搜索饥荒吧,然后点进饥荒吧进行浏览(别问为什么是饥荒吧,因为最近爱玩)
1.先创建一个工程pytestcode,在pytestcode下面创建一个模块test.py
2.导入uiautomator2取个别名u2,然后使用u2的connect_adb_wifi()方法进行连接,这个方法的参数是设备序列号(通过adb devices获取),连接后返回的device对象取名为d,使用d.info能够打印出设备的基本信息说明连接成功
3.启动指定的app其语法如下 d.app_start("指定的包名")
如何获取包名?可以先在手机上打开贴吧app,然后打印d.info,其中有个currentPackageName字段的值就是贴吧app的包名
4.点进百度贴吧之后,打开weditor UI查看器,刷新后鼠标移动到搜索按钮并点击,可以看到有两种定位方式可以选择,一种是resourceId,一种是xpath
注意:我们可以点击别的元素看看,会发现resourceId和某些元素是一模一样的,在这种resourceId不是唯一的情况下,如果我们以resourceId来定位,执行代码之后就会发现并没有反应,所以在这种情况下可以用xpath定位
xpath定位的语法:
d.xpath('元素定位表达式')
5. 强制等待与隐式等待,在打开app以后就能直接使用xpath找到元素并点击了吗?并不可以,因为代码执行的时间是很快的,可能执行到xpath点击元素的代码的时候,元素可能还没有加载出来,所以必须要进行等待,可以使用time.sleep()进行强制等待,但是我推荐使用d.implicitly_wait(等待时长) 隐式等待,隐性等待只需要加一次,全局通用。
隐性等待的语法:
d.implicitly_wait(等待时长) #单位是s
如果设置等待时长为10s,那么不管等待第几个元素最多是等待10s,如果需要的元素在2s就出现了,那么就执行下一步,并不会一直死等
因此代码如下:
import uiautomator2 as u2 #使用ip+端口号无线连接手机,参数是设备序列号,通过adb devices获取 d = u2.connect_adb_wifi('192.168.8.153:5555') #打印设备的基本信息 print(d.info) #启动百度贴吧 d.app_start("com.baidu.tieba") #隐式等待10s d.implicitly_wait(10) #通过xpath定位搜索按钮并点击 d.xpath('//*[@resource-id="android:id/content"]/android.widget.RelativeLayout[1]/androidx.viewpager.widget.ViewPager[1]/android.view.ViewGroup[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').click()
6. 点击搜索按键之后,需要在搜索框输入饥荒,然后点进饥荒吧,打开weditor UI查看器查看搜索框的信息,可以发现resourceId是唯一的,所以可以使用resourceId来定位
resourceId的定位语法:
d(resourceId = "元素定位表达式")
查看搜索框的信息
搜索结果如下:
uiautomator2支持使用文本作为元素定位方式
text的定位的语法:
d(text="元素定位表达式")
所以可以使用文本来定位饥荒吧并点击
代码如下:
import uiautomator2 as u2 #使用ip+端口号无线连接手机,参数是设备序列号,通过adb devices获取 d = u2.connect_adb_wifi('192.168.8.153:5555') #打印设备的基本信息 print(d.info) #启动百度贴吧 d.app_start("com.baidu.tieba") #隐式等待10s d.implicitly_wait(10) #通过xpath定位搜索按钮并点击 d.xpath('//*[@resource-id="android:id/content"]/android.widget.RelativeLayout[1]/androidx.viewpager.widget.ViewPager[1]/android.view.ViewGroup[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').click() #通过resourceId定位到搜索框并搜索饥荒 d(resourceId = "searchBox").send_keys("饥荒") #通过text定位来点进饥荒吧 d(text="42a98226cffc1e17a1d872fb4190f603728de991").click()
7. 滑动操作
滑动操作的语法:
d.swipe(fx,fy,tx,ty,duration)
获取屏幕的语法是:
d.window_size()
注:fx,fy表示的是起点的坐标,tx,ty表示的是终点的坐标,duration表示的是滑动持续的时间,在移动设备屏幕上,通常情况下坐标系统的原点(0,0)位于屏幕的左上角,即左上角的像素点被定义为坐标原点。从原点开始,向右为 X 轴正方向,向下为 Y 轴正方向。
那么起点和终点的坐标如何获取?为了适应不同的分辨率,我们可以先获取到屏幕的尺寸,然后分别乘以系数,为了加强滑动的稳定性,需要进行强制等待
点进饥荒吧之后,往上滑一秒,代码如下:
import time import uiautomator2 as u2 #使用ip+端口号无线连接手机,参数是设备序列号,通过adb devices获取 d = u2.connect_adb_wifi('192.168.8.153:5555') #打印设备的基本信息 print(d.info) #启动百度贴吧 d.app_start("com.baidu.tieba") #隐式等待10s d.implicitly_wait(10) #通过xpath定位搜索按钮并点击 d.xpath('//*[@resource-id="android:id/content"]/android.widget.RelativeLayout[1]/androidx.viewpager.widget.ViewPager[1]/android.view.ViewGroup[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.view.ViewGroup[1]/android.widget.ImageView[1]').click() #通过resourceId定位到搜索框并搜索饥荒 d(resourceId = "searchBox").send_keys("饥荒") #通过text定位来点进饥荒吧 d(text="42a98226cffc1e17a1d872fb4190f603728de991").click() #获取屏幕宽和高 width, height = d.window_size() #强制等待2s,之所以强制等待是因为点击饥荒吧之后会加载一段时间,为了等到屏幕出现再滑动,所以强制等待 time.sleep(2) #往上滑1s d.swipe(0.5 * width, 0.8 * height, 0.5 * width, 0.3 * width, 1) #停止app d.app_stop("com.baidu.tieba") #清理环境 d.app_clear("com.baidu.tieba")
weditor报错Local server not started, start with
1.先关闭启动weditor的cmd窗口
2.清理浏览器cookie缓存,以下以Google浏览器为例
- 先点击右上角三个点,选择设置
- 进入设置后点击隐私和安全,再点击清除浏览器数据
- 勾选以下数据并清除
3.重启ADB
adb kill-server
adb start-server
4.执行命令重连设备
adb connect ip:端口号
5.再次执行 python -m weditor
以上介绍的都是最基本的操作,还需要别的操作可以查看下面的文档
官方文档:
GitHub - openatx/uiautomator2: Android Uiautomator2 Python Wrapper
参考文档: