day06
- 能独立搭建app测试相关环境
- 能通过命令在电脑端操作android系统中的应用(adb命令)
day07
掌握appium基础操作api的使用(安装、卸载、…)
掌握appium高级api操作(拖拽、滑动、…)
掌握appium手机操作api(按键…)
day08
- 能使用api模拟手势的常用操作(轻敲、按下、抬起、长按、移动、等待)
- 能使用api对手机系统进行设置(网络、通知栏、按键)
获取分辨率、手机截图、获取和设置网络、发
送键到设备、打开和关闭通知栏- 扩展(切换环境(原生到webvier)、如何获取弹窗消息)
一、能独立搭建app测试相关环境
自动化用,手工也可以用,查看日志
1. 工具说明
- 主流工具
使用:appinum支持安卓和ios
- app自动化执行原理(
代码在电脑上执行,appium开启控制,手机自动执行)
- app类型(技术)
2. 环境搭建
- 所需环境
- jdk(为了使用android-sdk俩功能)
- android-sdk(1、ADB调试
2、uiautomatorviewer查看元素) - appium
- 模拟器
(1) Jdk安装
- 说明:为什么要安装jdk?
安卓应用或开发工具是使用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-setup-1.8.0.exe ,一直到完成即可。
- python的appium. api库
- 作用:自动化测试使用api
- 安装:
pip install Appium-Python-Client==1.2.0
(4)模拟器(使用mumu模拟器)
- 说明:安卓手机
- 安装:雷电、mumu、夜神,默认安装完成即可
mumu模拟器连接:
- 找到mumu模拟器的安装路径,进入目录\emulator\nemu\vmonitor
- cmd回车
- adb connect 127.0.0.1:7555
- 查看 adb devices
不使用雷电是因为,旁边字太小,一些软件打不开
3、 adb调试工具
- 说明:通过电脑,操作android系统的工具(命令)。
adb devices 查看是否连接上
(1)adb工作原理
(2)adb命令
1. 获取包名和启动名
- 包名:
一个安卓应用的唯一标识符,操作那个应用需要依赖包名 - 启动名:
应用中界面标识符,允许重复。
1、mac/linux: adb shell dumpsys window | grep usedApp
2、windows: adb shell dumpsys window | findstr usedApp
2. 上传和下载命令
- 上传:adb push 路径\xxx.txt /sdcard
手机里面存储的所有东西都在sdcard文件夹里面 - 下载:adb pull /sdcard/xxx.txt 本地文件夹路径
3. 启动时间命令
命令:adb shell am start -W 包名/启动名
注意:查看时间 一般要冷启动(应用程序没有启动)
冷启动:应用程序未启动
热启动:应用程序已启动在后台或当前页面。
4. 查看日志(测试app手工必用)
- 命令:adb logcat > d:\xxx.log
- 提示:对app操作时,要开启日志,记录app操作的步骤和异常。
比如忽然白屏 或 闪退怎么办,查看日志
使用重定向,复制电脑本地路径到重定向后面。不使用手机里面的地址,再拉出来费劲
5. 其他常用命令
提示:
1、adb start-server正常不需要手动启动,自动启动adb.exe进程。
当应用进程死机,需要执行杀服务,杀完后需要执行命令启动。
2、adb connect ip:端口 正常不要手动连接,系统会自动连接。如果执行adb devices没有看到设备列表,需要手动 连接
4、 uiautomatorviewer工具 查看元素定位信息 (相当于F12,不需要安装)
- 为什么要查看元素信息?
说明:自动化测试就是查找元素操作元素,要查找元素,就需要根据元素的信息来查找(id、class、text、…) - 如何查找?
使用:android SDK 自带工具:uiautomatorviewer工具
- 如何使用?
1、启动:(复制uiautomatorviewer,粘贴,回车)
或者配置使用ui回车,配置方法如下
2、截屏查看
配置ui技巧
太长记不住技巧:
1、复制并改名为ui,
2、cmd输入ui,即可打开
注意:不建议在源路径上改,时间长会找不着
使用常见问题
二、基础操作API
目标:能灵活运用Appium-基础api实现对于app应用的模拟测试过程脚本编写(基于unittest单元测试框架)
1、 入门示例
前置:必须启动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["unicodeKeyboard"] = True
desired_caps["resetKeyboard"] = True
# 获取driver
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_caps)
2、 基础api
(1)启动应用(应用跳转)
- 方法:driver.start_activity(包名,启动名)
- 说明:appium支持夸应用,可以在操作应用中切换到B应用。
(2)获取当前包名、启动名
- 方法
当前应用包名:driver.current_package
当前应用启动名:driver.current_activity - 练习
from time import sleep
from appium import webdriver
# 定义字典变量
desired_caps = {}
# 字典追加启动参数
desired_caps["platformName"] = "Android"
desired_caps["platformVersion"] = "7.1.1"
desired_caps["deviceName"] = "192.168.56.101:5555"
desired_caps["appPackage"] = "com.android.settings"
desired_caps["appActivity"] = ".Settings"
# 设置中文
desired_caps["unicodeKeyboard"] = True
desired_caps["resetKeyboard"] = True
# 获取drive
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_caps)
"""
需求:
1、启动设置后,暂停3秒,打开短信应用
2、打印当前默认应用包名启动名
"""
sleep(3)
# 启动短信
driver.start_activity("com.android.messaging",".ui.conversationlist.ConversationListActivity")
# 打印包名和启动名
print("当前所在应用包名:",driver.current_package)
print("当前所在应用启动名:",driver.current_activity)
driver.quit()
(3)其他基础Api练习(关闭app和驱动对象、安装卸载和判断是否安装、置于后台)
from time import sleep
from appium import webdriver
# 定义字典变量
desired_caps = {}
# 字典追加启动参数
desired_caps["platformName"] = "Android"
desired_caps["platformVersion"] = "7.1.1"
desired_caps["deviceName"] = "192.168.56.101:5555"
desired_caps["appPackage"] = "com.android.settings"
desired_caps["appActivity"] = ".Settings"
# 设置中文
desired_caps["unicodeKeyboard"] = True
desired_caps["resetKeyboard"] = True
# 获取driver
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_caps)
"""
需求:
1、判断百年奥莱是否安装,如果安装进行卸载,否则安装
2、启动设置界面
3、置于后台3秒钟
4、关闭设置界面
5、关闭app驱动
"""
# 判断百年奥莱是否安装
if driver.is_app_installed("com.yunmall.lc"):
print("百年奥莱app已存在正在卸载...")
# 卸载
driver.remove_app("com.yunmall.lc")
print("卸载百年奥莱app成功!")
else:
print("百年奥莱不存在,正在安装...")
# 安装
driver.install_app("/Users/lgy/PycharmProjects/lgy/bj37-web01/day07-appium01//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("退出driver驱动")
driver.quit()
3、元素定位
(1)单个元素定位
常用前面3个
- 需求
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_class_name("android.widget.EditText").send_keys("hello")
sleep(1)
print("使用xpath点击返回...")
# 点击返回 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()
(2)定位一组元素
需求
移动端里面id可以重复。有值有很多,无值不会报错。
# 1、获取所有id为:android:id/title
els = driver.find_elements_by_id("android:id/title")
for el in els:
print("元素id为com.android.settings:id/title的为本内容有:",el.text)
els = driver.find_elements_by_class_name("android.widget.TextView")
for el in els:
print("元素class为android.widget.TextView的为本内容有:",el.text)
els = driver.find_elements_by_xpath("//*[contains(@text,'设')]")
for el in els:
print("文本包含'设'内容有:",el.text)
sleep(3)
driver.quit()
4、元素操作
(1)点击、输入、清空
- 方法
1、点击:元素.click()
2、输入:元素.send_keys()
3、清空:元素.clear()
- 需求
# 设置中文
desired_caps["unicodeKeyboard"] = True
desired_caps["resetKeyboard"] = True
# 1、点击放大镜
driver.find_element_by_xpath("//*[@resource-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("你好")
sleep(3)
driver.quit()
(2)获取元素信息 (断言使用)
- 方法
获取文本:元素.text
获取大小:元素.size
获取位置:元素.location
- 需求
1、打开设置app
2、点击放大镜
3、获取搜索文本值
4、计算搜索框中心触摸点(计算坐标:中心区域长为 位置+大小的一半)
# 点击放大镜
driver.find_element_by_id("com.android.settings:id/search").click()
# 获取 菜单我的文本
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))
(3)获取元素属性 (获取属性值信息)
- 方法:
元素.get_attribute("属性名")
- 注意:
因为不仅支持Android,也支持ios,属性值名称不对应
- 需求:
# 点击放大镜
els = driver.find_elements_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、content-desc属性值为:",el.get_attribute("name"))
print("4、resource-id属性值为:",el.get_attribute("resourceId"))
print("5、class属性值为:",el.get_attribute("className"))
print("--"* 50)
5、滑动(常见)和拖拽
(1)swipe(start_x,start_y,end_x,end_y)
- 特点:精准滑动(基于两个坐标 点滑动)
- 说明:针对坐标点进行操作
无法从上往下滑动。
练习示例:
driver.swipe(100,1000,100,400,duration=2000)
(2) scroll
- 特点:滚动(有惯性存在,滚动下不按下第⼀个元素)
- 说明:针对两个元素进行操作
(3)drag_and_drop【推荐】
- 特点:拖拽(没有惯性,按下开始元素拖拽到指定元素位置)
- 说明:针对两个元素进行精准操作
三、高级手势操作API(超过俩元素)
说明:
1、appium中封装了手势的操作方法,都在TouchAction类中,需要导包
2、所有的手势操作,最终都需要调用perform()方法才能执行
- 为什么要使用手势的操作?
-- 红包雨、九宫格解决,都需使用手动操作,之前学习的api最多是支持2个元素之间或2个坐标点之间操作。
1、轻敲
- api:TouchAction(driver).tap(el,x,y).perform()
- 示例
from appium.webdriver.common.touch_action import TouchAction
wlan = driver.find_element_by_xpath("//*[@text='WLAN']")
TouchAction(driver).tap(wlan).perform()
2、按下与释放
- 按下: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()
3、长按
- 方法: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()
4、移动及等待
- 移动:move_to(el,x,y)
- 等待:wait(),
不等待没效果 - 案例:九宫格解锁
from time import sleep
from appium import webdriver
# 定义字典变量
from appium.webdriver.common.touch_action import TouchAction
desired_caps = {}
# 字典追加启动参数
desired_caps["platformName"] = "Android"
desired_caps["platformVersion"] = "6.0.1"
desired_caps["deviceName"] = "192.168.56.101:5555"
desired_caps["appPackage"] = "com.android.settings"
desired_caps["appActivity"] = ".Settings"
# 设置中文
desired_caps["unicodeKeyboard"] = True
desired_caps["resetKeyboard"] = True
# 获取driver
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_caps)
driver.implicitly_wait(10)
"""
需求:绘制解锁图案 Z
绘制坐标点:
1、1048,340 1377,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()
sleep(3)
driver.quit()
四、手机操作API(安卓系统)
- 说明:使用appium框架的api操作android
1、常用api
- 查看当前网络类型
- 设置网络类型(
要有权限) - 查看当前分辨率
- 截图
- 扩展网络类型
# 1、查看当前网络类型
print("当前网络类型为:",driver.network_connection)
# 2、设置网络类型为飞行模式
driver.set_network_connection(6)
print("设置之后的网络类型为:",driver.network_connection)
# 3、获取当前屏幕分辨率
print("当前屏幕分辨率为:",driver.get_window_size())
# 4、截图保存
driver.get_screenshot_as_file("./screen.png")
2、按键操作
"""
需求:
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
# 提示:部分模拟器没有按键操作效果
3、通知栏
应用场景:检查服务器发送的通知
"""
需求:
1、打开通知栏,点击通知栏的信息
"""
# 打开通知栏
driver.open_notifications()
sleep(2)
# 查找信息并点击
driver.find_element_by_xpath("//*[@text='应用宝.apk']").click()
五、扩展
1、获取toast消息
- 说明:toast消息为移动应用中,⼀种黑底白字提示信息,有时间限制。
- 为什么要获取toast消息?
断言内容 - 如何获取?
步骤
1、安装依赖库
2、配置driver启用参数
3、编写代码获取文本值
- 安装依赖库:pip install uiautomator2
- 配置driver启用参数
desired_caps['automationName'] = 'Uiautomator2'
- 编写代码获取文本值
# 获取toast消息
msg = driver.find_element_by_xpath("//*[contains(@text,'请先勾选同意')]").text
print("toast消息为:",msg)
2、 切换webview【了解】 UI自动化测试
- 为什么要切换?
app中嵌套web信息,如果不切换无法定位操作 - 如何切换?
1、获取当前环境 --> driver.contexts
2、调用切换方法 --> driver.switch_to.context("环境")
- 示例
# 获取当前所有的环境
print(driver.contexts)
# 切换环境
driver.switch_to.context("WEBVIEW_com.android.browser")
(2) monkey 性能测试
- 什么是money?
android系统自带一种测试压力的小工具,主要测试系统或应用稳定性。 - monkey测试什么?
测试是否崩溃、闪退、死机。 - 执行命令?
adb shell monkey -p com.yunmall.lc -v -v 10000 >xxx.log
-
-p:包名
-
-v -v:日志
-
10000:乱抓的时间次数-s:设置随机种子数(两次执行随机种子数⼀样,执行的事件也是⼀样)
-
其他参数
-
日志查看什么?
搜索:“ANR”、ERROR、null、相关错误