移动自动化测试

app自动化介绍

工具说明

  • 主流工具

image-20240721173241335

  • app自动化执行原理

image-20240721173358328

  • app类型(技术)

image-20240721173505030

环境搭建

  • 所需环境

    • 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工作原理

image-20240722084200850

  • adb命令
    • 获取包名和启动名
      • 包名:一个安卓应用的唯一标识符,操作哪个应用需要依赖包名
      • 启动名:应用中界面标识符,允许重复。
1、mac/linux:adb shell dumpsys window | grep usedApp
2、windows:adb shell dumpsys window | findstr usedApp

image-20240722084448375

  • 上传和下载命令
    • 上传:adb push 路径\xxx.txt/sdcard
    • 下载:adb pull/sdcard/xxx.txt本地文件夹路径
  • 启动时间命令
    • 命令:adb shell am start -W 包名/启动名

image-20240722091128357

注意:查看时间,一般要冷启动(应用程序没有启动)
冷启动:应用程序未启动
热启动:应用程序已启动在后台或当前页面。
  • 查看日志

    • 命令:adb logcat->d:\xxx.log
    • 提示:对app操作时,要开启日志,记录app操作的步骤和异常
  • 其他常用命令

image-20240722091411475

提示:
1、adb start-server 正常不需要手动启动,自动启动adb.exe进程。当应用进程死机,需要执行杀服务,杀完后
需要执行命令启动。
2、adb connect ip:端口 正常不要手动连接,系统会自动连接。如果执行adb devices 没有看到设备列表,需要
手动连接。

元素定位

查看元素定位信息

为什么要查看元素信息?
说明:自动化测试就是查找元素操作元素,要查找元素,就需要根据元素的信息来查找(id、
class、text、…)

  • 如何查找?

    使用:android SDK 自带工具:uiautomatorviewer工具
    
  • 如何使用?

    • 1、启动

    image-20240722215929130

2、截屏查看

image-20240722220001827

  • 使用常见问题

image-20240722220051529

元素操作

基础操作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练习

image-20240723214618301

"""
需求:
	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()

元素定位

  • 单个元素定位

image-20240723215743035

  • 需求

image-20240723215825620

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()
  • 定位一组元素

image-20240723220600271

  • 实现
#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()
  • 需求

image-20240724213021199

  • 代码
#输入中文 参数
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(“属性名”)
  • 注意:

image-20240724220627785

  • 需求:

image-20240724220653914

  • 代码:
#点击放大镜
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()
    • 示例
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

  • 查看当前网络类型
  • 设置网络类型
  • 查看当前分辨率
  • 截图
  • 扩展网络类型

image-20240725084922917

#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")
  • 按键操作

image-20240725085409247

"""
需求:
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

  1. 为什么要切换?

    app中 嵌套web信息,如果不切换无法定位操作
    
  2. 如何切换?

    1、获取当前环境-->driver.contexts
    2、调用切换方法 ->driver.switch_to.context("环境")
    
  • 示例

    #获取当前所有的环境
    print(driver.contexts)
    #切换环境
    driver.switch_to.context("WEBVIEW_com.android.browser")
    

monkey

  • 什么是monkey

    android系统自带一种测试压力的小工具,主要测试系统或应用稳定性。
    
  • monkey测试什么?

    测试是否崩溃,闪退,死机。
    
  1. 执行命令?

    adb shell monkey -p com.yunmall.lc -v -v 10000>xxx.log
    
    • -p:包名

    • -v-v:日志

    • 10000:乱抓的时间次数

    • -s:设置随机种子(两次执行随机种子数一样,执行的时间也一样)

    • 其他参数

    image-20240726081741787

  • 日志查看什么?

    搜索:“ANR”、ERROR、null、相关错误
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值