大家好。我是小蔡:
Web自动化讲完了。接下是移动端自动化。
移动端有:ios和安卓两大主流操作系统。
1.移动端自动化:(主流工具介绍)
Robtium:
是一款安卓的一款开源自动化测试框架,不支持跨平台,支持Java语言
Macaca:由阿里爸爸开发自动化解决方案,使用平台:pc端。安卓。Ios,支持语言:java,python,nodejs
Appium:是一个自动化测试开源工具,支持iOS和android平台上的移动原生应用、移动Web应用和混合应用。Appium是一个跨平台工具,它允许测试人员使用同样的接口、基于不同的平台写自动化测试代码,大大增加了测试套件间代码的复用性。
Appium特点:开源
移动原生应用:是指那些用iOS或者android sdk写的应用;
移动web应用:是指那些使用移动浏览器访问的应用,appium支持iOS的safari和android上的chrome;
混合应用:是指原生代码封装在网页视图(原生代码和web内容交互)。
支持跨平台,windos,linux,macos
自动化框架原理:
Python-------->appium服务器----(adb)---手机:appiumbootstrap.jar
Appium-client
通讯方式:发送http请求
需要环境:安卓SDK ,JDK
appium服务器安装:
需要配置SDK路径和JDK路径
Appiun-client-python安装
Adb工具原理:adb客户端,adb的服务器,adb守护进程

2.Adb常用命令:
Adb debices 查看手机的设备id名称以及状态,pffline(关闭)/device(在线)
Adb strat-server 启动
Adb kill-server 关闭
获取包名和界面名(为以后移动自动化获取界面定位元素打下基础)
包名:app包名,通过app包名来区分不同的app,app包名是唯一
界面名:相当于web页面当中的链接地址,app当中,每一个界面都有一个名字
操作步骤:
1.在手机或者模拟器开打app
Adb shell dumpsys window windows | grep(linux)/findstr(win) mFocusedApp #获取当前打开的包名和界面名称。
Adb shell dumpsys window|findstr/grep”usedApp”
![]()
2.通过aapt dump badging+app安装包路径+文件名称

PS:推荐代码启动app端的时候 使用aapt获取包名和界面名
app安装:adb install app路径+app安装包名称
app卸载:adb uninstall 包名
上传:将电脑上的文件上传到手机
Adb push 电脑上的文件路径 远端手机的路径(根目录)
下载:从手机下载文件到本地
Adb pull 手机的文件路径 电脑的文件夹路径
查看日志信息:
定位问题:
Adb logcat 来查看相关的日志信息
可以使用管道符将日志信息输出到文本文件中
Adb logcat > 文件名.log
App启动速度命令(性能测试)
Aab shell am start -w 包名/界面名
3..Appium基础:
使用hello Appium
能够使用appium启动任意应用程序
能够了解“前置代码”各项参数含义
前置代码(如下)#导包
From appium import webdriver
Import time
Desired_caps=dict()
#平台的版本 大小写无所谓
Desired_cpas[‘platformName’]=’Android’
#平台版本号
Desired_cpas[‘platformVersion’]=5.1
#设备名称IOS 不能乱写 安卓可以乱写
Desired_cpas[‘deviceName’]=’可以随便叫’
#可以打开的应用程序(包名)
Desired_cpas[‘’appPackege]=’com.adbroid.setting’
#要打开的界面(界面名称)
Desired_cpas【appActivity】)=’.Settings’
#一个地址,一个字典
Driver= webdriver.Remot(‘http://localhost:4723/wd/hub’,desired_caps)
参数含义:
1python代码会访问本机appium 4723的一个端口
2python会访问本机appium服务器,并获取driver对象
3appium会将driver对象转化为post七牛
4appium服务接收到会发情给手机
appium的基础API:
在脚本内启动其他app
应用场景:
#脚本内启动app
#参数:
appPac kag e:要打开的程序的包名
appActivity:要打卡的程序的界面名
Driver.start_activity(appPackage,appActiity)
你需要使用adb命令去获取包名和界面名称
获取app的包名和界面名称
方法:
#获取包名
Driver.current_package
#获取界面名
Driver.current_activity
关闭app和驱动对象
#关闭当前操作app,不会关闭驱动对象
Driver.close_app()---会退出到桌面。
#关闭驱动对象,同事关闭所有关联的app
Driver.quit()-----会杀死driver驱动对象。
安装和卸载以及是否安装app
示例:判断某APP是否已经安装
如果安装,就卸载,如果不安装,就安装。代码如下
if driver.is_app_installed(“包名”)
Driver.remove_app(“包名”)
Else:
Driver.install_app(“包名”)
将应用置于后台(模拟按HOME键)
app放置到后台一定时间再回到前台,模拟热启动
参数:
Seconds:后台停留多少秒
方法
Driver.background_app(5)
新工具:
UIAutomatorViewer的使用
定位元素的时候必须根据元素的相关特征来进行定位,而UIAutomatorViewer就是用来获取元素特征的,如:火狐浏览器的小鼠标
- 进入sdk目录下的目录
mac在tools/bin目录下,打开UIAutomatorViewer
windows在tools目录下,打开UIAutomatorViewer.bat
操作步骤:
- 打开安卓模拟器
- 启动待测app
- 点击UIAutomatorViewer左上角Device Screenshot
- 点击希望查看的控件
- 查看右下角Node Detall相关信息
Ps: 自动打开的命令窗口不要关
UIAutomatorViewer闪退
点击获取元素报错---
解决方案:adb kill-server
adb start-server
元素定位操作API
应用场景:
操作步骤:
- 打开UIAutomatorViewer工具
- 打开模拟器或真机
- 通过UIAutomatorViewer工具获取想要操作元素Node Detail信息
- 通过元素定位API进行定位
- 对元素进行相关操作
Ps:元素的定位基于当前屏幕范围内的可见元素
定位一个元素【掌握】:
应用场景:进行输入。进行点击。获取内容
id操作方法:
#通过id定位一个元素
#参数id_value:元素resource-id属性值
#返回值:
定位到单个元素
Driver.find_element_by_id(id_value)
class操作方法:
#通过class定位一个元素
#参数id_class:元素class属性值
#返回值:
定位到单个元素
Driver.find_element_by_id(id_class)
xpath操作方法:
#通过xpath定位一个元素
#参数xpath_value:元素content-desc属性值
#返回值:
定位到单个元素
Driver.find_element_by_xpath(xpath_value)
代码示例:
Search_button=Driver.find_element_by_id(“元素id”)
Search_button.click()
Serach_button.send_keys(“输入值”)
Ps:尽量找唯一素的元素
定位一组元素【掌握】:
应用场景:
和定位一个元素相同,但是想要批量的获取某个相同特征元素,使用一组元素的方式更加方便
方法名:
id操作方法:
#通过id定位一组元素
#参数id_value:元素resource-id属性值
#返回值:
定位到元素列表
Driver.find_elements_by_id(id_value)
class操作方法:
#通过class定位一组元素
#参数id_class:元素class属性值
#返回值:
定位到元素列表
Driver.find_elements_by_id(id_class)
xpath操作方法:
#通过xpath定位一组元素
#参数xpath_value:元素content-desc属性值
#返回值:
定位到元素列表
Driver.find_elements_by_xpath(xpath_value)
#通过id形式,获取所有id为“com.android.settings:id/title”元素,并且打印文字内容
titles=Driver.find_elements_by_id(“com.android.settings:id/title”)
Print(titles)
Print(len(titles))
For title in titles:
Title.text
#通过xpath的形式,获取所有包含“设”的元素,并且打印
titles=Driver.find_elements_by_xptah(“[//*【contains(@test,设 】)]”)
注意事项点:
Driver.find_elements_by_xx() #不会报错
Driver.find_element_by_xx() #会报错
传入一个不存在的值
元素等待
显式/隐式等待
隐式等待:
针对所有定位元素的超时时间设置为同一个值的时候
超出时间 抛出NoSuchElementException异常
步骤:
From selenium.webdriver.support.wait import webDriverwait
Driver.implicitly_wait(5)
...#搜索元素,点击等
显示等待:
针对所有定位元素设置超时时间设置为不同的值的时候
概念:
等待元素加载指定时长,超出时长抛出TimeoutException异常
步骤:
创建一个webDriverWait对象
调用WebDriverWait对象的until方法
代码:
参考Web自动化显示等待作用
显示等待隐式等待的选择:
作用域:
元素操作
- 点击元素
- 输入文字
- 清空文字
- 获取文本内容
- 获取元素位置和大小
- 能够代码根据属性名获取元素的属性值
方法名称
点击:
Element.click()
Driver.find_element_by_id(“xxx”).click()
输入清空:
PS:若要输入中文,需要在手机参数中多加两行代码
Desired_caps[‘unicodeKeyboard’] = ture
Desired_caps[‘resetKeyboard’ ]=ture
Element.send.keys(value)
Element.clear()
获取元素的文本内容:
需要获取按钮,文本框,输入框等控件的文本内容使用
返回值:
控制的文本内容
Element.text
代码:
Eles=driver.find_elements_by_id(元素id)
For i in eles:
Print(i.text)
获取元素的位置和大小
获取element的位置
返回值:
字典,x为元素的x坐标,y为元素的y坐标
Element.location
后去element的大小
字典,width为宽度,heigtht为高度
Element.size
获取元素的属性值
使用元素属性名获取对应的属性值
enabled属性:元素是否可以用
对element进行点击操作
参数:
Value:要获取的属性名
返回值:
根据属性名得到的属性值
Element.get_attribute(value)# value:元素的属性
Eles=driver.find_elements_by_id(元素id)
For i in eles:
Print(i.get_attribute(“enabled”))
特殊属性处理:
Resource-id属性值---需要传入值为resourceId且API>18
className 属性值--- 需要传入ClassName返回class属性且API>18
Content-desc/name属性值--需要传入name
滑动和拖拽事件:
swipe滑动屏幕
scroll滑动屏幕
Drag_and_drop滑动屏幕
swipe滑动事件:
从一个坐标的位置滑动到另外一个坐标位置,只能是两个点之间的滑动
方法名:
参数:
Start_x/y :起点坐标
End_x/y : 终点坐标
Duration:滑动这个操作一共持续的时间长度,:ms
Driver.swipe(100,100,100,100,duration=2000)
存在一定误差
Ps:滑动误差越长,误差越靠后
相同距离时,持续时间越长,惯性越小
为什么存在滑动误差:【非重点】
图解:
XXXX
Scroll/drag_and_drop滑动事件:
Scroll从一个元素滑动到另外一个元素,直到页面自动停止
drag_and_drop第一个元素位置会被第二个元素替代
参数:
Origin_el: 滑动开始的元素
Destination_el 滑动结束的元素
Driver.scroll/drag_and_drop(origin_el,Destination_el)
小结:不能设置时间,惯性很大
滑动和拖拽事件的选择:
分为四种:
有惯性,传入元素--scroll
无惯性,传入元素drag_and_drop
有惯性,传入坐标swipe,并且设置较短的duration时间
无惯性,传入坐标swipe,并且设置较长的duration时间
高级手势TouchAction:
使用代码完成轻敲手势
使用代码完成按下手势
使用代码完成抬起手势
使用代码完成等待手势
使用代码完成长按手势
使用代码完成手指移动手势
然后我们将这些基本手势组合成一个相对复杂的手势。比如解锁手机c操作步骤:
1.创建TouchAction
2.通过对象调用想执行的手势
3.通过perform()进行执行。
#轻敲案例
找到元素
Wlan_button=driver.find_element_by_xpath(“路径”)
创建TouchAction
Touch_action=TouchAction(driver)
通过对象调用想执行的手势
Touch_action=Touch_action.tap(Wlan_button)
通过perform()进行执行
Touch_action.perform()
简化两步:
Wlan_button=driver.find_element_by_xpath(“路径”)
TouchAction(driver).tap(Wlan_button).perform()
TouchAction(driver).tap(x=100,y=200,count=次数).perform()
#按下和抬起操作【掌握】
应用场景
模拟手指一直按下,模拟手指抬起,可以组合成敲击或长按
按下方法名
参数:el元素 x:坐标 y:y坐标
TouchAction(driver).press(el=none/x=none,y=none).perform()
按下-抬起方法名
TouchAction(driver).press(el=none/x=none,y=none).release().perform()
#等待操作【掌握】
模拟手指等待,比如按下后等待5秒之后再抬起
方法名
参数ms:暂定的毫毛速
TouchAction(driver).press(el=none/x=none,y=none).wait(2000).release().perform()
#长按操作
长按弹出某一个菜单信息
方法名:
参数:
El:元素
X:x坐标
Y:y坐标
Duration:长按时间,毫秒
TouchAction(driver).longpress(x=400,y=400,duration=2000).release().perform()
长按==按下,等待,抬手
#长按操作
手势解锁需要先按下,在移动
方法名 move_to
El:元素
X:X坐标
Y:坐标
TouchAction(driver).move_to(元素,x=,y=).perform()
案例:
- 获取界面名称
- 启动手势解锁中
怎么获取界面某一个点。
打开UI Automator Viewer最大化,观察右手边红叉叉的旁边的坐标
代码:
TouchAction(druver).press(x=?,y=?).move_to(x=?,y=?).move_to(x=..,y=..).release().perform()
手机操作API
- 获取手机分辨率
- 获取手机截图
- 获取和设置网络状态
- 能过发送键到设备
- 能够打开和关闭手机通知栏
获取手机分辨率【掌握】:
自动化测试可能需要根据当前设备的屏幕分辨率来计算一些或者点击滑动的坐标
#获取手机分辨率,(返回值是一个字典)
Driver.get_window_size()
获取手机截图【截图】:
#参数是图片名称/也可以是路径
Driver.get_screenshot_as_file(“screen.png”)
获取和设置手机网络【掌握】
需要对切换网络的时候,需要有一个弹窗提示
#获取当前网络并且打印
Driver.network_connection
0-None 000
1-Airplane mode 001
2-Wifi only 010
3-Data only 1 0 0
4-All network on 1 1 0
#设置手机网络
方法名
参数:
connectionType:网络类型
Driver.set_network_connnection(connection(connectionType))
Driver.set_network_connnection(1)
扩展:判断是否为流量
导入 ConnectionType这个类
If driver.network_connection == ConnectionType.DATA_ONLY:
Print(1)
Else:
Print(0)
发送键到设备【掌握】
模拟返回键,home键等等操作。
方法名:press_keycode
Keycode:发送设备的关键代码
Metastate:关于被发送的关键代码元信息,
Driver.press_keycpde(keyconde,metastate=None)
Ps:
按键对应的编码,可以在百度搜索关键字’android keycode’
操作手机通知栏【掌握】
如何打开通知栏
Driver.open_notifications()
如何关闭通知栏
appium官方并没有提供关闭通知api.
现实当中。怎么关闭就怎么关闭
Driver.prees_keycode(4)
浙公网安备 33010602011771号