python + uiautomator2测试框架搭建

一、介绍

        uiautomator2 是一个可以使用Python对Android设备进行UI自动化的库,仅支持Android平台的原生应用测试。。其底层基于Google uiautomator,Google提供的uiautomator库可以获取屏幕上任意一个APP的任意一个控件属性,并对其进行任意操作。它提供便利的python接口。允许测试人员直接在PC上编写Python的测试代码,操作手机应用,完成自动化测试,大大提高自动化代码编写的效率。 

        原理解释:
        python端:运行脚本,往移动端发送HTTP请求
        移动端:安装atx-agent,然后atx-agent启动uiautomator2服务进行监听,并识别python脚本,转换为uiautomator2的代码。
        移动设备通过WIFI(同一网段)或USB接收到PC上发来的HTTP请求,执行制定的操作
​​​​​​​
二、安装

        安装 uiautomator2,
                命令行窗口:pip install -U uiautomator2
        设备安装atx-agent:                         

# init就是所有USB连接电脑的手机上都安装uiautomator2
python -m uiautomator2 init


三、安装weditor

        在APP自动化测试是,需要使用到元素定位,UI元素定位的工具--WEditor,方便我们快速的识别手机上的元素,方便写代码。WEditor能够提供辅助编写脚本,定位元素,调试代码等功能,是基于python的一个查看APP元素的工具。
        安装命令:pip install weditor==0.6.4  
        由于直接命令pip install weditor会报错,解决方法 太麻烦,所以直接降版本安装。
        查看安装是否成功:weditor --help
        使用:命令行窗口输入:python -m weditor   ,默认启动后,会直接在本地打开一个网页,接下来的操作都可以只在这个网页完成。


四、操作及应用

        1、链接手机

        device = uiautomator2.connect()  ,用的最多的是默认只有一台连接,或指定序列号链接。

import uiautomator2 as u2

#链接设备,这里是通过adb链接手机的;所以要提前装好adb;并能够adb devices发现该设备;
#用的最多的是默认的和指定序列号的,最方便
#不提供参数,默认连接方式,适用于只有一台设备
#device = u2.connect()

#有多台设备,指定设备ip,通过USB链接, 我的设备序列号是127.0.0.1
#device = u2.connect('127.0.0.1')

#通过wifi链接,设备IP要和PC在同一网络;在夜神模拟器,查到的序列号和ip同样
#device = u2.connect_wifi('127.0.0.1')

#打开被测试的app
device(text='浏览器').click()

注:用adb devices 查看当前pc链接的所有设备。

        2、APP操作:安装、卸载、启动

        这些操作都需要 用到app 的包名:device.app_current()

import uiautomator2 as u2

#链接设备,这里是通过adb链接手机的;所以要提前装好adb;并能够adb devices发现该设备;
#用的最多的是默认的和指定序列号的,最方便
#不提供参数,默认连接方式,适用于只有一台设备
#device = u2.connect()

#有多台设备,指定设备ip,通过USB链接, 我的设备序列号是127.0.0.1
device = u2.connect('127.0.0.1')

#通过wifi链接,设备IP要和PC在同一网络
#device = u2.connect_wifi('127.0.0.1')

#安装apk
#device.app_install("http://www.baidu.com/abc.apk")

#获取正在运行的apk的包名
pkgname = device.app_current
print(pkgname)

#卸载app,参数是包名
#device.app_uninstall(pkgname)

#启动app,传入要打开apk 的包名
device.app_start(pkgname)
#点击启动,打开被测试的app
device(text='浏览器').click()

#关闭app
device.app_stop(pkgname)

#清楚APP的数据,通常测试时不希望上次测试的动作影响下一次的测试;所以可以清除一下
device.app_clear(pkgname)

        3、获取pkg_name

                通过代码获取正在运行的APP包名:

#获取所有正在运行的APP包名
print(device.app_list_running())
#获取当前正在运行的APP包名
print(device.app_current())

                adb指令获取:在命令行窗口输入命令

adb shell dumpsys activity | find "mFocusedActivity"
adb shell dumpsys activity top | findstr ACTIVITY 

        4、设备操作

                获取设备信息


#以字典的形式打印设备信息
print(device.info)
# 获取窗口大小
print(device.window_size())
# 获取当前应用程序信息。对于某些android设备,输出可以为空
print(device.current_app())
# 获取设备序列号
print(device.serial)
# 获取WIFI IP
print(device.wlan_ip)
# 获取详细的设备信息
print(device.device_info)

        5、截图        

#截屏,两种方式,
#先截后存
image = device.screenshot()
image.save("image_path.jpg")
# 截屏并保存
device.screenshot("image_path.")

        6、文件推拉

# 推送到文件夹
device.push("text.txt", "/sdcard/")
# 推送后重命名
device.push("text.txt", "/sdcard/new_name.txt")
# 推送 fileobj
with open("text.txt", 'rb') as f:
    device.push(f, "/sdcard/")
# 推动和更改文件访问模式,755是Linux里的7:可读可写可执行;
device.push("text.sh", "/data/local/tmp/", mode=0o755)

#拉取文件
device.pull("/sdcard/text.txt", "text.txt")
# 如果在设备上找不到文件,FileNotFoundError将引发
device.pull("/sdcard/file_not_exists.txt", "text.txt")

        7、按键操作

device.screen_on()#打开屏幕 
device.screen_off() #关闭屏幕

device.press("home") # 点击home键
device.press("back") # 点击back键
device.press("left") # 点击左键
device.press("right") # 点击右键
device.press("up") # 点击上键
device.press("down") # 点击下键
device.press("center") # 点击选中
device.press("menu") # 点击menu按键
device.press("search") # 点击搜索按键
device.press("enter") # 点击enter键
device.press("delete") # 点击删除按键
device.press("recent") # 点击近期活动按键,最近浏览的APP
device.press("volume_up") # 音量+
device.press("volume_down") # 音量-
device.press("volume_mute") # 静音
device.press("camera") # 相机
device.press("power") #电源键

#更多具体查看Android keyCode

五、元素定位

        UiAutomator定位用于Android APP的元素定位,使用UI Automator API(UISelector类)来搜索特定元素。Android APP页面布局用的是xml 可扩展标记语言,类似于HTML,可以粗俗的把元素定位理解为HTML的元素定位;下面是 UiSelector 类的一些常用接口使用方法。

        元素定位辅助工具:weditor,UI元素定位的工具--WEditor,方便我们快速的识别手机上的元素,方便写代码。WEditor能够提供辅助编写脚本,定位元素,调试代码等功能,是基于python的一个查看APP元素的工具。weditor运行时,会在浏览器打开一个页面,这个页面辅助我们定位APP上的元素。

        命令行窗框输入:weditor ,会在浏览器打开页面,手机上的内容就全部展示在浏览器上;相当于web页面打开 F12控制台一样效果。左侧,相当于手机页面,可以直接操作;中间显示元素属性,相当于F12控制台;右边显示录制脚本的代码。右下Hierarchy,点击名称,显示元素控件位置。

        最上面部分,是管理手机的,例如Android、ios;例如链接那台手机;dunp Hierarchy 刷新;
        weditor优势在于:一、可以同时管理多台设备;二、直接在调试界面操作手机,不需要另一只手去动手机;三、右边coding区自动生成脚本对应 python 代码。

        元素构成:控件由空间名称、控件属性、子控件构成;每个控件的控件名称、属性,都可以weditor页面中间模块找到;根据名称、属性,找到对应控件,指定执行操作,名称和属性可以组合使用。

        定位方式:根据weditor中间模块的 prop结构词定位;ui2支持 android 中 UiSelector 类中的所有定位方式。具体参考官方文档

名称 描述
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为符合指定正则的元素

示例代码:        

import uiautomator2 as u2
#导入元素定位辅助工具
import weditor

#adb连接手机
device = u2.connect('127.0.0.1')

#定位元素并操作;这些属性可以组合使用
device(text='浏览器').click()
#或者先定位,后操作
element = device(textStartsWith='浏览')
element.click()

         子元素和兄弟定位

                根据上下级关系进行定位;上级:页面的外层;下级:页面的内层;同级:sibling,同一级。        

#子元素定位:
#查找类名为android.widget.ListView下的Bluetooth元素
device(className="android.widget.ListView").child(text="Bluetooth")

#兄弟元素定位
element = device(textContains='个人中心', className='android.widget.TextView')
#若是只有一个兄弟元素,可以不用传参
element.sibling(text='购物车').click()

        相对位置定位

                相对定位可以定位某个元素的前后左右元素,定位速度慢,因为要做页面渲染;不建议用。括号里面可以添加相对定位的目标元素结构词方法,不添加,则默认选择对应位置的第一个元素。

element = device(textContains='个人中心', className='android.widget.TextView')
 
element.left(text='评价').click()  #不填参数,则默认左边第一个元素
element.right(text='购物车').click()
element.up(text='付款').click()
element.down(text='订单').click()

        元素常用api:如 element.exists() ,判断 element 元素是否存在。

方法 描述 返回值 备注
exists() 判断元素是否存在 True,Flase @property装饰的类属性方法
info 返回元素的所有信息 字典 @property装饰的类属性方法
get_text() 返回元素文本 字符串
set_text(text) 设置元素文本 None
clear_text() 清空元素文本 None
center() 返回元素的中心点位置 (x,y) 基于整个屏幕的点


        

六、APP操作:点击、拖动、滑动、长按

        点击: click:        
        device(text='').click() ,通过元素定位;
        device.click(x,y) 通过全局坐标点击,元素定位不便时使用;

        滑动:device.swipe

        输入:先定位元素,再输入;
                输入:element.send_keys()
                清空:element.clear_text()

七、智能等待

        强制等待是 time.sleep(5);这个等待时间是固定的,智能等待,等待事件完成,然后开始进行下一步;主要有:
        device.app_start('package_name',wait=true)  ;等待APP启动完成;不需要time.sleep(),加上wait=true;
        device.wait_activity()
        device(text'='button').wait()  等待button元素出现
        device(text='password').wait_gone()  等待password元素消失
        device().exist()         等待元素是否存在
        device.implicitly_wait()      设置等待超时时间,也可单独给元素设置;如device().click(tiimeout=10)。
​​​​​​​        等待点击,设置隐式等待后: click() ,  clear_text()
        
八、toast

        展示及获取toast弹窗信息

#展示toast信息
device.toast.show("Hello world")

#获取toast信息
device.toast.get_message()

九、案例实战

        

猜你喜欢

转载自blog.csdn.net/guanrongl/article/details/124819473