app自动化介绍
工具说明
- 主流工具
- app自动化执行原理
- app类型(技术)
环境搭建
-
所需环境
- JDK
- android-sdk
- appium
- 模拟器
-
1、JDK安装
- 说明:为什么要安装JDK?
1、安卓应用或开发工具是使用JAVA语言开发,必须使用jdk。
- 安装
下载安装包后直接以管理员方式安装,下一步到最后即可。
-
2、android-sdk
-
说明:android工具包
-
安装:
- 1、解压到指定目录
- 2、将目录添加到path中
1、新建环境变量:ANDROID_HOME=D:\android\sdk(这里为安装目录) 2、添加path路径,在path中添加:%ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools; 提示:tools有查看元素工具,我们必须使用;platform-tools是adb命令工具所在目录。
-
-
3、appium安装
- 说明:
需要安装appium服务端程序和python中调用的api库
- 服务端:
- 作用:将脚本发送给手机
- 安装:双击安装程序
appium-desktop-1.8.0.exe
,一直到完成即可。
- python的appium.api库
- 作用:自动化测试使用api
- 安装:
pip install Appium-Python-Client==1.2.0
- 说明:
-
4、模拟器
- 说明:安卓手机
- 安装:
雷电、mumu、夜神,默认安装完成即可
adb命令
说明:通过电脑,操作android系统的工具。
- adb工作原理
- adb命令
- 获取包名和启动名
- 包名:
一个安卓应用的唯一标识符,操作哪个应用需要依赖包名
- 启动名:
应用中界面标识符,允许重复。
- 包名:
- 获取包名和启动名
1、mac/linux:adb shell dumpsys window | grep usedApp
2、windows:adb shell dumpsys window | findstr usedApp
- 上传和下载命令
- 上传:
adb push 路径\xxx.txt/sdcard
- 下载:
adb pull/sdcard/xxx.txt本地文件夹路径
- 上传:
- 启动时间命令
- 命令:
adb shell am start -W 包名/启动名
- 命令:
注意:查看时间,一般要冷启动(应用程序没有启动)
冷启动:应用程序未启动
热启动:应用程序已启动在后台或当前页面。
-
查看日志
- 命令:
adb logcat->d:\xxx.log
- 提示:
对app操作时,要开启日志,记录app操作的步骤和异常
- 命令:
-
其他常用命令
提示:
1、adb start-server 正常不需要手动启动,自动启动adb.exe进程。当应用进程死机,需要执行杀服务,杀完后
需要执行命令启动。
2、adb connect ip:端口 正常不要手动连接,系统会自动连接。如果执行adb devices 没有看到设备列表,需要
手动连接。
元素定位
查看元素定位信息
为什么要查看元素信息?
说明:自动化测试就是查找元素操作元素,要查找元素,就需要根据元素的信息来查找(id、
class、text、…)
-
如何查找?
使用:android SDK 自带工具:uiautomatorviewer工具
-
如何使用?
- 1、启动
2、截屏查看
- 使用常见问题
元素操作
基础操作API
-
入门示例
前置:必须启动appium服务、模拟器。
from appium import webdriver #定义字典变量 desired_caps={} #字典追加启动参数 desired_caps["platformName"]="Android" #注意:版本号必须正确 desired_caps["platformVersion"]="7.1.1" #android不检测内容,但是不能为空 desired_caps["deviceName"]="192.168.56.101:5555" desired_caps["appPackage"]="com.android.settings" desired_caps["appActivity"]=".Settings" #设置中文 desired_caps["nicodeKeyboard"]=True desired_caps["resetKeyboard"]=True #获取driver driver=webdriver.Remote("http://127.0.0.1:4723/wd/hub",desired_caps)
-
基础api
- 启动应用
- 方法:
driver.start_activity(包名,启动名)
- 说明:appium支持跨应用,可用在操作应用中切换到B应用。
- 方法:
- 获取当前包名、启动名
- 方法
- 当前应用包名:driver.current_package
- 当前应用启动名:driver.current_activity
- 方法
- 练习
""" 需求: 1、启动设置后,暂停3s,打开短信应用 2、打印当前默认应用包名启动名 """ sleep(3) #启动短信 driver.start_activity("com.android.messaging","ui.conversationlist.ConversationListActivity") #打印包名和启动名 print("当前所在应用包名:",driver.current_package) print("当前所在应用启动名:",driver.current_activity) driver.quit()
- 启动应用
-
其他基础API练习
"""
需求:
1、判断百年奥莱是否安装,如果安装进行卸载,否则安装
2、启动设置界面
3、置于后台3秒钟
4、关闭设置界面
5、关闭app驱动
"""
#判断百年奥莱是否安装
if driver.is_app_installed("com.yunmall.lc"):
print("百年奥莱app已存在正在卸载...")
#卸载
driver.remove app( "com.yunmal1.1c)
else:
print ("百年奥莱不存在,正在安装")
#安装
driver.install_app("/Users/1gy/PycharmProjects/1gy/bj37-web01/day07-appiumo1//bainianaolaitemai_115.apk")
print ("安装百年奥莱app成功!")
sleep(3)
#启动设置界面
print ("启动设置界面")
driver. start activity("com.android.settings, .Settings")
sleep(3)
print ("设置应用置于后台3秒钟。。。")
#置于后台3秒
driver.background_app(3)
print ("关闭设置app...")
#关闭设置
driver.close app()
print ("获取关闭后的app报名")
print ("关闭设置app,后获取包名:",driver.current_package)
sleep(3)
print ("卸载百年奥莱app成功!")
print ("退出driver 驱动")
driver.quit()
元素定位
- 单个元素定位
- 需求
print("使用id点击放大镜...")
#使用id->点击放大镜
driver.find_element_by_id("com.android.settings:id/search").click()
sleep(1)
print("使用class输入搜索hello...")
#使用class 上输入hell
driver.find_element_by_classname("android.widget.EditText").send_keys("hello")
sleep(1)
print("使用xpath点击返回...")
driver.find_element_by_xpath("//*[@class='android.widget.ImageButton']").click()
sleep(1)
print("使用name点击搜索...")
#使用name定位
driver.find_element_by_accessibility_id("搜索设置").click()
sleep(3)
driver.quit()
- 定位一组元素
- 实现
#1、获取所有id为:android:id/title
els=driver.find_element_by_id("android:id/title")
for el in els:
print("元素id为com.android.settings:id/title的为本内容有:",el.text)
els=driver.find_element_by_class_name("android.widget.TextView")
for el in els:
print("元素class为android.widget.TextView为本内容有:",el.text)
els=driver.find_element_by_xpath("//*[contains(@text,'设')]")
for el in els:
print("文本包含'设'内容有:",el.text)
元素操作
- 方法
1、点击:元素.click()
2、输入:元素.send_keys()
3、清空:元素.clear()
- 需求
- 代码
#输入中文 参数
desired_caps["unicodeKeyboard"]=True
desired_caps["resetKeyboard"] = True
#1、点击放大镜
driver.find_element_by_xpath( "//*[aresource-id='com.android.settings: id/ search").click()
#2、输入hello
el=driver.find_element_by_xpath("//*[@resource-id='android:id/search_src_text']")
el.send_keys(hello)
#3、2s清空内容
sleep(2)
el.clear()
#4、5s输入你好
sleep(2)
el.send_keys("你好")
元素获取信息
-
方法
- 获取文本:元素.text
- 获取大小:元素.size
- 获取位置:元素.location
-
需求
1、打开设置app
2、点击放大镜
3、获取搜索文本值
4、计算搜索框中心触摸点
-
代码
#获取菜单我的文本 text= driver.find_element_by_xpath("//*[@resource-id='android:id/search_src_text']").text print ("我的菜单,文本值为:",text) location= driver.find_element_by_xpath("//*[@resource-id='android:id/search_src_text']").location print ("位置:",location) size = driver.find_element_by_xpath("//*[@resource-id='android:id/search_src_text']").size print ("大小为:",size) X= location.get("x") + (size.get("width"/2) y= location.get("y")+(size.get("height")/2) print ("触摸中心位置x:{}y:{}".format (x,y))#获取菜单我的文本 text= driver.find_element_by_xpath("//*[@resource-id='android:id/search_src_text']").text print ("我的菜单,文本值为:",text) location=driver.find_element_by_xpath("//*[@resource-id='android:id/search_src_text']").location print ("位置:",location) size= driver. find_element_by_xpath("//*[ @resource-id='android:id/search-src-text']").size print ("大小为:",size) X= location.get("x")+(size.get("width")/2) y=location.get("y")+(size.get("height")/2) print ("触摸中心位置x:{}y:{}".format (x,y))
获取元素属性
- 方法:元素.get_attribute(“属性名”)
- 注意:
- 需求:
- 代码:
#点击放大镜
driver.find_element_by_id("com.android.settings:id/title")
for el in els:
print("--"*50)
print("1、enabled属性值为:"el.get_attribute("enabled"))
print("2、text属性值为:"el.get_attribute("text"))
print("3、context-desc属性值为:"el.get_attribute("name"))
print("4、resource-id属性值为:"el.get_attribute("resourceId"))
print("5、class属性值为:"el.get_attribute("className"))
print("--"*50)
手势滑屏
滑动
- swipe(start_x,start_y,end_x,end_y)
- 特点:精准滑动(基于两个坐标点滑动)
- 说明:针对坐标点进行操作
- 练习示例
driver.swipe(100,1000,10,400,duration=2000)
-
scroll
- 特点:滚动(有惯性存在,滚动不下按第一个元素)
- 说明:针对两个元素进行操作
-
drag_and_drop【推荐】
- 特点:拖拽(没有惯性,按下开始元素拖拽到指定元素位置)
- 说明:针对两个元素进行精准操作
手势操作
说明:
1、appium中封装了手势的操作方法,都在TouchAction类中,需要导包
2、所有的手势操作,最终都需要调用perform()方法才能执行
- 为什么要使用手势的操作?
--红包雨、九宫格解决,都需使用手动操作,之前学习的api最多是支持2个元素之间或2个坐标点之间操作。
- 轻敲
- api:
TouchAction(driver).tap(el,x,y).perform()
- 示例
- api:
from appium.webdriver.common.touch_action import TouchAction
wlan=driver.find_element_by_xpath("//*[@text='WLAN']")
TouchAction(driver).tap(wlan).perform()
-
按下与释放
- 按下:
press(el,x,y)
- 释放:
release()
- 示例
#获取WLAN元素 wlan=driver.find_element_by_xpath("//*[@text='WLAN']") loc=wlan.location print(loc) #效果类似点击 TouchAction(driver).press(x=loc.get("x"),y=loc.get("y")).release().perform()
- 按下:
-
长按
- 方法:
long_press(el,x,y)
- 常见:
在移动应用中,有时候需要长按才能激活菜单选项
- 示例:
#获取WLAN元素 wlan=driver.find_element_by_xpath("//*[@text='WLAN']") wlan.click() #必须暂停一定时间 暂停3秒(原因:元素未加载出来,直接长按坐标没有任何效果) sleep(3) #效果类似点击 TouchAction(driver).long_press(x=777,y=375).perform()
- 方法:
-
移动及等待
- 移动:move_to(el,x,y)
- 等待:
wait()
- 案例:九宫格解锁
""" 需求:绘制解锁图案Z 绘制坐标点: 1、1048,340 1337,340 1707,340 2、1377,669 3、1048,999 1377,999 1707,999 """ #1、定位WLAN WLAN=driver.find_element_by_xpath("//*[@text='WLAN']") #2、定位应用 app=driver.find_element_by_xpath("//*[@text='应用']") driver.drag_and_drop(app,WLAN) #3、点击安全 driver.find_element_by_xpath("//*[@text='安全']").click() #4、点击屏幕锁定方式 driver.find_element_by_xpath("//*[@text='屏幕锁定方式']").click() #5、点击图案 driver.find_element_by_xpath("//*[@text='图案']").click() #必须暂停,登录绘制页面加载完成 sleep(2) #6、绘制 TouchAction(driver).press(x=1048,y=340).wait(100).move_to(x=1377,y=340).wait(100).move_to(x=1707,y=340).wait(100) .move_to(x=1377,y=669).wait(100).move_to(x=1048,y=999).wait(100).move_to(x=1377,y=999).wait(100).move_to(x=1707,y=999).wait(100).perform()
手机操作API
说明:使用appium框架的api操作android
常用api
- 查看当前网络类型
- 设置网络类型
- 查看当前分辨率
- 截图
- 扩展网络类型
#1、查看当前网络类型
print("当前网络类型为:",driver.network_connection)
#2、设置网络类型为飞行模式
driver.set_network_connection(1)
print("设置之后的网络类型为:",driver.network_connection)
#3、获取当前屏幕分辨率
print("当前屏幕分辨率为:",driver.get_window_size())
#截图保存
driver.get_screenshot_as_file("./screen.png")
- 按键操作
"""
需求:
1、点击三次音量+24
2、点击返回 4
3、点击两次音量- 25
"""
i=0
#三次增大音量
while i<3:
driver.press_keycode(24)
i+=1
sleep(2)
#点击返回
driver.press_keycode(4)
i=0
#两次减少音量
while i<2:
driver.press_keycode(25)
i+=1
#提示:部分模拟器没有按键操作效果
- 通知栏
应用场景:检查服务器发送的通知
"""
需求:
1、打开通知栏,点击通知栏的信息
"""
#打开通知栏
driver.open_notifications()
sleep(2)
#查找信息并点击
driver_find_element_by_xpath("//*[@text='应用宝.apk']").click()
其他延伸
获取toast消息
-
说明:
toast消息为移动应用中,一种黑底白字提示信息,有时间限制。
-
为什么要获取toast消息?
断言内容
-
如何获取?
- 步骤
- 安装依赖库
- 配置driver启动参数
- 编写代码获取文本值
- 安装依赖库:
pip install uiautomator2
- 配置driver启动参数
desired_caps['automationName']='uiautomator2'
- 编写代码获取文本
#获取tosat消息 msg=driver.find_element_by_xpath("//*[contains(@text,'请先勾选同意')]").text print("toast消息为",msg)
- 步骤
切换webview
-
为什么要切换?
app中 嵌套web信息,如果不切换无法定位操作
-
如何切换?
1、获取当前环境-->driver.contexts 2、调用切换方法 ->driver.switch_to.context("环境")
-
示例
#获取当前所有的环境 print(driver.contexts) #切换环境 driver.switch_to.context("WEBVIEW_com.android.browser")
monkey
-
什么是monkey
android系统自带一种测试压力的小工具,主要测试系统或应用稳定性。
-
monkey测试什么?
测试是否崩溃,闪退,死机。
-
执行命令?
adb shell monkey -p com.yunmall.lc -v -v 10000>xxx.log
-
-p:包名
-
-v-v:日志
-
10000:乱抓的时间次数
-
-s:设置随机种子(两次执行随机种子数一样,执行的时间也一样)
-
其他参数
-
-
日志查看什么?
搜索:“ANR”、ERROR、null、相关错误