APP移动端测试高级(一)

一、Appium介绍

Appium是一个移动端的自动化框架,可用于测试原生应用、移动网页应用和混合型应用,且是跨平台的。可用于IOS和Android以及firefox的操作系统。

原生的应用是指用android或ios的sdk编写的应用;移动网页应用是指网页应用,类似于ios中safari应用或者Chrome应用或者类浏览器的应用;混合应用是指一种包裹webview的应用,原生应用于网页内容交互性的应用。

重要的是Appium是跨平台的,何为跨平台,意思就是可以针对不同的平台用一套api来编写测试用例。

二、环境搭建

主要几个点如下:

1. appium安装

直接解压即可,打开Appium.exe

启动成功展示如下:

2. Appium库安装

# 安装
pip install Appium-Python-Client
# 检验是否成功
pip list

三、Appium使用

1. 打开模拟器或真机的应用

①打开手机应用
②打开Appium
③创建一个python项目,并创建一个文件
④将下面代码复制到文件中
⑤获取当前应用包名和启动activity并修改文件

from appium import webdriver
# server 启动参数
desired_caps = dict()
# 设备信息
# 平台信息,不区分大小写
desired_caps['platformName'] = 'Android'
# 系统版本,7.1.2可以写[7 ,7.1 , 7.1.2]
desired_caps['platformVersion'] = '7.1.2'
# 设备名称,可以随便写,但是不能乱写,Android可以随便写,但是ios必须正确的写
desired_caps['deviceName'] = 'emulator-5554'
# app的信息
desired_caps['appPackage'] = 'com.android.settings'
desired_caps['appActivity'] = '.Settings'
# 声明我们的driver对象
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
driver.quit()

2. 脚本内启动其他app

driver.start_activity(appPackage,appActivity)

3. 关闭app

driver.close_app()  # 关闭当前操作的app,不会关闭驱动对象

4. 关闭驱动对象

driver.quit()   # 关闭驱动对象,同时关闭所有关联的app

三、App基础操作API

完成app自动化需要一些基础条件的支持,本节将讲解APP初始化API。

3.1前置代码

# server 启动参数

desired_caps = {}
desired_caps['platformName'] = 'Android' 
desired_caps['platformVersion'] = '5.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)

3.2 安装APK到手机

driver.install_app(app_path) 

参数:app_path:脚本机器中APK文件路径

3.3 手机中移除APP

driver.remove_app(app_id) 

参数:app_id:需要卸载的app包名

3.4 判断APP是否已安装

driver.is_app_installed(bundle_id) 

参数:bundle_id: 可以传入app包名,返回结果为True(已安装) / False(未安装)
3.5 发送文件到手机

import base64
data = str(base64.b64encode(data.encode('utf-8')),'utf-8')
driver.push_file(path,data)
参数:

path:手机设备上的路径(例如:/sdcard/a.txt)
data:文件内数据,要求base64编码
Python3.x中字符都为unicode编码,而b64encode函数的参数为byte类型,需要先转码;
生成的数据为byte类型,需要将byte转换回去。

3.6 从手机中拉取文件

import base64
data = driver.pull_file(path) # 返回数据为base64编码
print(str(base64.b64decode(data),'utf-8')) # base64解码

参数: path: 手机设备上的路径

3.7获取当前屏幕内元素结构

driver.page_source  

作用:返回当前页面的文档结构,判断特定的元素是否存在

四、手机控件查看工具uiautomatorviewer

4.1 工具简介

用来扫描和分析Android应用程序的UI控件的工具.

4.1 如何使用

  1. 进入SDK目录下的tools目录,打开uiautomatorviewer
  2. 电脑连接真机或打开android模拟器
  3. 启动待测试app
  4. 点击uiautomatorviewer的左上角Device Screenshot,会生成app当前页面的UI控件截图

     

  5. 选择截图上需要查看的控件,即可浏览该控件的id,class,text,坐标等信息

     

五、APP元素定位操作

手工测试主要通过可见按钮操作,而自动化是通过元素进行交互操作。
元素的基本定位基于当前屏幕范围内展示的可见元素。

5.1 Appium常用元素定位方式

namevalue
idid属性值
classclass属性值
xpathxpath表达式

5.2 前置代码

from appium import webdriver
# server 启动参数
desired_caps = {}
# 设备信息
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '5.1'
desired_caps['deviceName'] = '192.168.56.101:5555'
# app的信息
desired_caps['appPackage'] = 'com.android.settings'
desired_caps['appActivity'] = '.Settings'

# 声明我们的driver对象
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)

5.3 通过id定位

  • 方法:find_element_by_id(id_value) # id_value:为元素的id属性值
  • 业务场景:
    1. 进入设置页面
    2. 通过ID定位方式点击搜索按钮
  • 代码实现:
    driver.find_element_by_id("com.android.settings:id/search").click()
    driver.quit()
    

5.4 通过class定位

  • 方法:find_element_by_class_name(class_value) # class_value:为元素的class属性值
  • 业务场景:
    1. 进入设置页面
    2. 点击搜索按钮
    3. 通过class定位方式点击输入框的返回按钮
  • 代码实现:
# id 点击搜索按钮
driver.find_element_by_id("com.android.settings:id/search").click()
# class 点击输入框返回按钮
driver.find_element_by_class_name('android.widget.ImageButton').click()
driver.quit()

5.5 通过xpath定位

  • 方法:find_element_by_xpath(xpath_value) # xpath_value:为可以定位到元素的xpath语句
    android端xptah常用属性定位:
    1. id ://*[contains(@resource-id,'com.android.settings:id/search')]
    2. class ://*[contains(@class,'android.widget.ImageButton')]
    3. text ://*[contains(@text,'WLA')]
    模糊定位 contains(@key,value): value可以是部分值
  • 业务场景:
    1. 进入设置页面
    2. 点击WLAN菜单栏
  • 代码实现:
    # xpath 点击WLAN按钮
    driver.find_element_by_xpath("//*[contains(@text,'WLA')]").click()
    

5.6 定位一组元素,注意element -> elements

应用场景为元素值重复,无法通过元素属性直接定位到某个元素,只能通过elements方式来选择,返回一个定位对象的列表.

5.7 通过id方式定位一组元素

  • 方法: find_elements_by_id(id_value) # id_value:为元素的id属性值
  • 业务场景:
    1. 进入设置页面
    2. 点击WLAN菜单栏(id定位对象列表中第1个)
  • 代码实现:
    # 定位到一组元素
    title = driver.find_elements_by_id("com.android.settings:id/title")
    # 打印title类型,预期为list
    print(type(title))
    # 取title返回列表中的第一个定位对象,执行点击操作
    title[0].click()
    

5.8 通过class方式定位一组元素

  • 方法:find_elements_by_class_name(class_value) # class_value:为元素的class属性值
  • 业务场景:
    1.进入设置页面
    2.点击WLAN菜单栏(class定位对象列表中第3个)
  • 代码实现:
    title = driver.find_elements_by_class_name("android.widget.TextView")
    # 打印title类型,预期为list
    print(type(title))
    # 取title返回列表中的第一个定位对象,执行点击操作
    title[3].click()
    for index, item in enumerate(ele_list):
      print(index, item.text)  ```
    

5.9 通过xpath方式定位一组元素

  • 方法:find_elements_by_xpath(xpath_value) # xpath_value:为可以定位到元素的xpath语句
  • 业务场景:
    1. 进入设置页面
    2. 点击WLAN菜单栏(xpath中class属性定位对象列表中第3个)
  • 代码实现:
    # 定位到一组元素
    title = driver.find_elements_by_xpath("//*[contains(@class,'widget.TextView')]")
    # 打印title类型,预期为list
    print(type(title))
    # 取title返回列表中的第一个定位对象,执行点击操作
    title[3].click()
    

六、WebDriverWait 显示等待操作

在一个超时时间范围内,每隔一段时间去搜索一次元素是否存在,如果存在返回定位对象,如果不存在直到超时时间到达,报超时异常错误。

  • 方法:WebDriverWait(driver, timeout, poll_frequency).until(method)
    参数:
    1.driver:手机驱动对象
    2.timeout:搜索超时时间
    3.poll_frequency:每次搜索间隔时间,默认时间为0.5s
    4.method:定位方法(匿名函数)
  • 匿名函数:
    lambda x: x
    等价于python函数:
    def test(x):
    return x
  • 使用示例:
    WebDriverWait(driver, timeout, poll_frequency).until(lambda x:x.find_elements_by_id(id_value))
    
  • 解释:
    1.x传入值为:driver,所以才可以使用定位方法。
  • 函数运行过程:
    1.实例化WebDriverWait类,传入driver对象,之后driver对象被赋值给WebDriverWait的一个类变量:self._driver
    2.until为WebDriverWait类的方法,until传入method方法(即匿名函数),之后method方法会被传入self._driver
    3.搜索到元素后until返回定位对象,没有搜索到函数until返回超时异常错误.
  • 业务场景:
    1.进入设置页面
    2.通过ID定位方式点击搜索按钮
  • 代码实现:
    from selenium.webdriver.support.wait import WebDriverWait # 导入WebDriverWait  类
    # 超时时间为30s,每隔1秒搜索一次元素是否存在,如果元素存在返回定位对象并退出
    search_button = WebDriverWait(driver, 30, 1).until(lambda driver:driver.find_element_by_id("com.android.settings:id/search"))
    search_button.click()
    driver.quit()
    

七、APP元素信息操作API

本节讲介绍手机端元素信息的获取以及基本的输入操作。

7.1. 点击元素

ele.click()

7.2.发送数据到输入框

  • 方法:send_keys(vaue) # value:需要发送到输入框内的文本

  • 业务场景:
    1.打开设置
    2.点击搜索按钮
    3.输入内容abc

  • 代码实现:

    # 点击搜索按钮
    driver.find_element_by_id("com.android.settings:id/search").click()
    # 定位到输入框并输入abc
    driver.find_element_by_id("android:id/search_src_text").send_keys("abc")
    
  • 重点:大家可以将输入的abc 改成 输入中文,得到的结果:输入框无任何值输入且程序不会抱错
    解决输入中文问题:

      1.server 启动参数增加两个参数配置
          desired_caps['unicodeKeyboard'] = True
          desired_caps['resetKeyboard'] = True
    
      2.再次运行会发现运行成功
          # 点击搜索按钮
          driver.find_element_by_id("com.android.settings:id/search").click()
          # 定位到输入框并输入abc
          driver.find_element_by_id("android:id/search_src_text").send_keys("积云教育")
    

7.3. 清空输入框内容

  • 方法:clear()
  • 业务场景:
    1.打开设置
    2.点击搜索按钮
    3.输入内容abc
    4.删除已输入abc
  • 代码实现:
    # 点击搜索按钮
    driver.find_element_by_id("com.android.settings:id/search").click()
    # 定位到输入框并输入abc
    input_text = driver.find_element_by_id("android:id/search_src_text")
    # 输入abc
    input_text.send_keys("abc")
    time.sleep(1)
    # 删除abc
    input_text.clear()
    

7.4. 获取元素的文本内容

  • 方法: text
  • 业务场景:
    1.进入设置
    2.获取所有元素class属性为“android.widget.TextView”的文本内容
  • 代码实现:
    ele_list = driver.find_elements_by_class_name("android.widget.TextView")
    for e in ele_list:
        print(e.text)
    for index, item in enumerate(ele_list):
        print(index, item.text)
    
  • 执行结果:
      0 设置
      1
      2 移动数据网络已关闭
      3 无线和网络
      4 WLAN
      5 "guest"
      6 蓝牙
      7 已停用
      8 流量使用情况
      9 已使用 0 B 的数据
      10 更多
      11 设备
      12 显示
      13 自动调节亮度功能已关闭
      14 通知
      15 已允许所有应用发送通知
    

7.5. 获取元素的属性值

  • 方法: get_attribute(value) # value:元素的属性
    ⚠️ value='name' 返回content-desc / text属性值
    ⚠️ value='text' 返回text的属性值
    ⚠️ value='className' 返回 class属性值,只有 API=>18 才能支持
    ⚠️ value='resourceId' 返回 resource-id属性值,只有 API=>18 才能支持

  • 业务场景:
    1.进入设置
    2.获取搜索按钮的content-desc属性值

  • 代码实现:

    # 定位到搜索按钮
    get_value = driver.find_element_by_id("com.android.settings:id/search")
    print(get_value.get_attribute("content-desc"))
    执行结果:
            搜索
    

7.6. 获取元素在屏幕上的坐标

  • 方法:location
  • 业务场景:
    1.进入设置页面
    2.获取搜索按钮在屏幕的坐标位置
  • 代码实现:
# 定位到搜索按钮
get_value = driver.find_element_by_id("com.android.settings:id/search")
# 打印搜索按钮在屏幕上的坐标
print(get_value.location)
{'y': 44, 'x': 408}

7.7. 获取app包名和启动名

  • 获取包名方法:current_package
  • 获取启动名:current_activity
  • 业务场景:
    1.启动设置
    2.获取包名和启动名
  • 代码实现:
    print(driver.current_package)
    print(driver.current_activity)
    
  • 执行结果:
    com.tencent.news
    .activity.SplashActivity
    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值