7.1 主流框架优缺点剖析

1. APP 主要测试策略

  • 安装、卸载测试:
  • 安装:1)安装路径;2)安装环境(平台、安全软件);3)安全权限(获取位置、摄像头、通讯录、ROOT管理员等权限);4)安装的版本;5)严酷测试:a)安装过程中取消;b)安装过程中重启、关机;c)内存不足下安装;d)无网或弱网下进行安装验证;
  • 卸载:1)安装路径下删除对应的文件;2)写入系统部分的信息进行删除(PC注册表);3)卸载过程中取消、重启;4)卸载释放空间(软件所产生的数据信息、缓存、应用程序空间)
  • UI测试:
  • (如菜单、对话框、窗口和其它可规控件)布局、风格是否满足客户要求、文字是否正确、页面是否美观、文字、图片组合是否完美、操作是否友好等
  • 主要包含三部分内容:导航、图形、内容
  • 功能测试:
  • 1)运行APP(安装完成后打开APP、加载进度、APP页面切换、注册/登录/注销)、2)应用的前后台切换(前后台切换、锁屏、电话、强杀APP再开启、需要处理的提示框时前后台切换、数据交互时前后台切换)、
  • 3)免登陆(app有免登陆时考虑版本差异、无网络时是否可免登陆、切换用户登录后,校验登录信息及数据更新,原用户退出、一用户登录另外一设备,原设备退出、app前后台切换、更改密码后,数据交互身份校验、用户退出后,下次是登录界面)、
  • 4)数据更新、离线浏览、APP更新、定位/相机服务、时间测试、PUSH测试
  • 性能测试
  • 交叉事件测试
  • 升级、更新测试
  • 用户体验测试
  • 硬件环境测试
  • 客户端数据库测试
  • 安全测试

2. 几个主流的框架

Android UI 自动化的两大类:   1)Android(UI Automator):通过 Android 提供的服务获取当前窗口的视图信息

              2)基于 Instrumentation 把测试APK 和被测 APK,运行一个进程中,通过 Java 反射机制获取当前窗口的所有视图,根据该视图获取目标控件的属性

  • UI Automator:优点:1)Android 提供,基本支持所有的 Android 事件;2)相对 Instrumentation,不需要了解代码实现细节; 3)基于 Java,测试代码简单;4)跨APP,可打开如相册等其他功能;
  • 缺点:只支持 SDK16(Android 4.1)及以上,不支持 Hybrid APP、Web APP
  • Espresso(基于 Instrumentation):Google开源自动化框架,相对 Robotium 和 UI Automator,规模小、简洁,测试代码简单,易上手。不能跨 APP
  • Selendroid(基于 Instrumentation):可测试 Native APP、Hybrid APP、Web APP。 缺点:资料少
  • Robotium (基于 Instrumentation):应用较多。缺点:测试需要有 java 基础,了解 Android 基本租金,不能跨 APP
  • Appium:目前主流

7.2 Appium 框架

1. Appium 是开源、跨平台的测试框架,可测试 iOS、Android、Firefox OS 的模拟器和真机。使用 WebDriver 的 JSON wire 协议来驱动 Apple 的 UI Automation 及 Android 的 UI Automator 框架。

Q: 自动化测试过程中,涉及的相关数据有哪些类型及如何处理?

分析:测试过程中涉及到哪些数据?
=> 业务流所需的(测试数据、用户数据)、环境数据、程序中的固定数据(常量数据) 通常,
1)程序中固定数据,一般会设置为常量数据;
2)业务测试数据,一般直接提取分离到相应的数据格式文件(csv/yaml/json/xml),有可以将该部分数据直接从数据库中读取(access/sqlite/mysql/oracle)
3)环境配置相关数据一般会提取到 ini、data、xml 等格式文件

2. Appium 日志分析

# 1. 获取当前模拟器的 android 版本
adb shell getprop ro.build.version.release # 2. 获取当前模拟器的 sdk 版本
adb shell getprop ro.build.version.sdk # 3. 获取当前模拟器的分辨率
adb shell vm size # 4. 获取机型、品牌
adb shell getprop ro.product.model
adb shell getprop ro.product.manufactuer # 5. 如设定 app 参数,实际是将 app 指定路径的 apk 先上传到模拟器或手机中,然后再进行安装;默认的上传路径是: /data/local/tmp/appium_cache # 6. dos 下安装app 命令是 adb install -r xxxx.apk,如进入手机终端其命令是 adb shell pm install -r xxxx.apk

7.3 Desired Capabilities

1. 官方说明文档:http://appium.io/docs/en/writing-running-appium/caps/index.html

2. 如需要与模拟器建立会员,需申明的值有:

desired_caps = {
"platformName": "Android",
"platformVersion": "7.1.2",
"deviceName": "3141a881",
"appPackage": "com.gece.intelligence",
"appActivity": "com.hdme.hdjy.controller.SplashActivity",
"skipServerInstallation": True,
"noReset": True
}

3. 需要注意的事项有:

  • 1)capbilities 的键名严格区分大小写,是关键字
  • 2)capbilites 的键名不能有空格
  • 3)start appium server before create session
  • 4)appium-server 与模拟器建立连接时需保证 adb devices 时能正常获取到设备,如提示版本不一致,可将 模拟器路径下的 adb 备份,再讲 android sdk 下的 adb 复制到模拟器路径下

7.4 Appium 元素定位

7.4.1. app 元素定位工具:

  • 1)appium-server 的 appium-inspect:appium-server 中新建一个 session,填入对应的 desired_capabilities,打开 app
  • 2)android-sdk \ tools \ uiautomatorviewer.bat 【注意:JDK1.8 可以正常使用,JDK17 时会运行不了,后续有方法时再更新】
  • 前提:手机/模拟器 与其他连接(如 appium-server)断开,否则被占用

7.4.2. 元素定位方法:

需要注意 app 的类型:

  • 1)原生 app: 支持 id,class_name, xpath。 其他5种在 HTML5 上支持
  • 2)web app:支持 selenium 的 8 种定位
  • 3)混合 app:即 原生+HTML5 的混合应用,定位视情况而定

7.4.3 原生 app 的定位方式

1)id:-> resource-id (app 里 id 一般是唯一的)
self.driver.find_element(By.ID, "com.tencent.mm:id/f3d").click() 2)class_name: -> class (app 里,class_name 一般不唯一,通常使用复数形式)
self.driver.find_elements(By.CLASS_NAME, "android.widget.Buton")[1].click() 3)Xpath
3.1) resource-
id 唯一
self.driver.find_element(By.XPATH, "//*[@resource-id='com.tencent.mm:id/fam']").click() 3.2)class 属性唯一
3.2.1)作为标签
self.driver.find_element(By.XPATH, "//android.widget.Button").click()
3.2.2)class 作为属性
self.driver.find_element(By.XPATH, "//*[@class='//android.widget.Button']").click() 3.3)text 值唯一
self.driver.find_element(By.XPATH, "//*[@text='登录']").click() 3.4) contains 模糊匹配
self.driver.find_element(By.XPATH, "//*[contains(@text, '登')]").click() 3.5)组合定位
# 如 class_name 和 id 的组合
id_class = '//android.widget.Button[@resource-id="com.tencent.mm:id/fam"]'
self.driver.find_element(By.XPATH, id_class).click() 3.6) 层级定位
father_son = '//*[@resource-id="com.tencent.mm:id/fam"]/android.widget.Button[1]'
self.driver.find_element(By.XPATH, father_son).click()

7.5 Appium 高级元素定位及扩展

7.5.1. accessibility_id

    android 上其属性对应 content-desc;IOS 上对应 label 或 name

self.driver.find_element_by_accessibility_id("More Info").click()

7.5.2. 坐标点定位

一般需要根据 屏幕大小计算相对比例。适应于 实在无法定位的情况下,或跳转第三方软件如微信分享

# driver 下的 tap() 传 1个或多个 (x,y) 元组的列表
self.driver.tap([(x1, y1), (x2, y2)], duration)

7.5.3.  uiautomator 定位

1)text 方法,-> 对应 text 属性

# 1)text
login_text = 'text("登录")'
driver.find_element_by_android_uiautomator(login_text).click() # 2)textContains
login_textContains = 'textContains ("录")'
driver.find_element_by_android_uiautomator(login_textContains ).click() # 3)textStartWith
login_textStart = 'textStart("登")'
driver.find_element_by_android_uiautomator(login_textStart).click() # 4)textMatches
login_textMatches = 'textMatches (".*")' // 参数需要传入一个正则表达式
driver.find_element_by_android_uiautomator(login_textMatches ).click()

2)resouceId 方法 -> 对应 resouce-id

id = 'resourceId("com.tencent.mm:id/fam")'
driver.find_element_by_android_uiautomator(id).click()

3)className 方法 -> 对应 class 属性

className = 'className("android.widget.Button")'
driver.find_element_by_android_uiautomator(className).click()

4)组合定位

# 如 resouceId 和 text 组合
IdText = 'resouceId("com.tencent.mm:id/fam").text("登录")'
driver.find_element_by_android_uiautomator(IdText).click() # className 和 text 组合
classText = 'className("android.widget.Button").text("登录")'
driver.find_element_by_android_uiautomator(classText).click()

5)父子定位

# 通过父元素定位子元素:父元素.childSelector(子元素)
fatherChild = 'resourceId("com.tencent.mm:id/fan").childSelector(className("android.widget.Button"))'
driver.find_element_by_android_uiautomator(fatherChild).click()

6)兄弟定位

# 通过同级元素定位同级元素,方式:好定位的兄弟属性.fromParent(较难定位的属性)
brother = 'resourceId("com.tencent.mm:id/faw").fromParent(className("android.widget.Button"))'
driver.find_element_by_android_uiautomator(brother).click()
注意:
1. 所有方法前面都省略了 创建对象
如 login.text = 'text("登录")', 其完整的是:
login.text = 'new UiSelector().text("登录")' 2. 所有方法体内的参数必须是 双引号 "",外面是 单引号 '',原因是 new UiSelector() 是 java 对象,其字符串参数必须 双引号。
======== 最新的 selenium 4.5 语法 =========
from appium import webdriver
from Read_Ini import ReadIni
from appium.webdriver.common.appiumby import AppiumBy
from time import sleep class StartAPP(object): def __init__(self, desired_caps, **kwargs):
self.driver = webdriver.Remote(command_executor="http://%s:%s/wd/hub" % (kwargs["server_address"], kwargs["sever_port"]),
desired_capabilities=desired_caps)
self.driver.implicitly_wait(10) def to_custom_page(self):
sleep(3)
hangqing_icon = 'className("android.widget.TextView").text("行情")'
self.driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, hangqing_icon).click() my = "//android.widget.TextView[@text='我的']"
self.driver.find_element(AppiumBy.XPATH, my).click() if __name__ == '__main__':
appium_config = ReadIni()
ini_path = "app_appium_config.ini" start_app = StartAPP(appium_config.read_ini(ini_path, "desired_capabilities"), **appium_config.read_ini(ini_path, "server_info"))
start_app.to_custom_page()

7)TouchAction 坐标/元素定位

from appium.webdriver.common.appiumby import AppiumBy
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.support.wait import WebDriverWait def qq_login_TouchAction2(self):
# 另外一个方式,该元素可定位,但无法点击。通过 selenium 的 WebDriverWait 的显式等待
# tap() 参数可以是元素,也可以是坐标点
id = 'resourceId("com.tencent.mobileqq:id/btn_login")'
try:
get_element = WebDriverWait(self.driver, 10, 1).until(lambda dir:dir.find_element(AppiumBy.ANDROID_UIAUTOMATOR, id))
TouchAction(self.driver).tap(x=500, y=1700).perform()
except:
print(sys.exc_info())

7.6 Appium API 及对象识别

1. appium 常用的 API

appium 官方文档:http://appium.io/docs/en/about-appium/intro/

driver.launch_app() 重新启动 desired capabilities 中定义的 app  
driver.close_app() 关闭 desired capabilities 中定义的 app driver.quit() 和 driver.close() 是针对 H5的,原生 app 需要使用 close_app()
    以上两个方法通常是针对初始化的 app 实现启动和关闭操作

driver.start_activity(app_package, app_activity)

driver.active_app(app_package)

启动一个指定包的 app

当 app 处于后台运行时,可以用该命令重新唤起

launch_app 是重新启动 app

driver.terminate_app(app_package) 结束一个指定包的 app  
     
driver.background_app(secs)

将初始化 app 置于后台 多少秒

其中 -1/null 表示一直处于后台

1). 过 n 秒后,会重新回到前台;

2). -1/null 会一直置于后台,可以使用 start_activity() 再将其调用出来

    3)driver.press_keycode(3) 按下 home 的方式让app 置于后台
     

driver.press_keycode(code)

driver.long_press()

driver.send_keys()

对应手机的键盘操作

1. 对应关系:https://developer.android.com/reference/android/view/KeyEvent

(需要FQ)

2. 如需发送中文,需要在 desired capabilities 中定义:

unicodeKeyboard = true,  resetKeyboard = true

     

driver.swipe(start_x, start_y, end_x, end_y, duration) 坐标滑动

driver.scroll(from_element, to_element) 基于元素位置滑动

driver.drag_and_drop(from_element, to_element) 基于元素位置拖拽

   
     

1)tap 单击:

TouchAction(driver).tap(element).perform()

TouchAction(driver).tap(x, y).perform()

2)press and release

TouchAction(driver).press(x, y).perform()

TouchAction(driver).press(x, y).release().perform()

TouchAction(driver).press(x, y).wait(1000).release().perform()

3)move_to 移动,可用于手势密码操作

TouchAction(driver).press(x,y).move_to(x1, y1).move_to(x2,y2).\

...release().perform()

  from appium.webdriver.common.touch_action import TouchAction

7.7 Native 与 WebView

1. 小程序:基于微信或支付宝平台上的 H5 页面的运行方式(依赖浏览器)

2. WebView:基于 WebKit 引擎,采用 chromium (android 4.4+)及 WebKit (< android 4.4)

3. 如何判定当前页面是原生的还是 H5

  • 1)原生是 activity 窗口间的切换;H5 是访问页面,会出现加载进度条。如果有进度条则说明有 H5 嵌套
  • 2)无网情况下,原生可以正常加载当前页面元素;H5 则无法显示
  • 3)如果页面有关闭操作,则基本为 H5

4. 如果需要获取当前程序中的所有 context(上下文)状态,则 app 必须为 debug 状态

如果是使用模拟器,则需要进行如下操作:

  • 1)安装逍遥模拟器
  • 2)模拟器中安装 xposed 框架(xposed 版本与模拟器的操作系统版本要一致)
  • 3)将 webviewhook.apk 组件加载到 框架中
  • 4)模拟器中安装 chrome 浏览器,且正常打开
  • 5)PC 上 chrome 浏览器输入 chrome://inspect/#devices,至此,app 上如果有 webview 的相关信息,会显示在浏览器中

读后笔记 -- Python 全栈测试开发 Chapter7:移动自动化测试框架的更多相关文章

  1. 【Python全栈-后端开发】嵩天老师-Django

    嵩天老师-Python云端系统开发入门教程(Django) 视频地址:https://www.bilibili.com/video/av19801429 课前知识储备: 一.课程介绍: 分久必合.合久 ...

  2. 【Python全栈-后端开发】Django入门基础

    Django基础知识 一. 什么是web框架? 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的 ...

  3. 【Python全栈-后端开发】Django进阶2-Form表单

    Django进阶2-Form表单 Django的Form主要具有一下几大功能: 生成HTML标签(可以保留上次输入内容) 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页 ...

  4. 【Python全栈-后端开发】数据库进阶

    数据库进阶 python关于mysql的API---pymysql模块 pymsql是Python中操作MySQL的模块,其使用方法和py2的MySQLdb几乎相同. 模块安装 pip install ...

  5. 【Python全栈-后端开发】Django进阶之Model操作复习

    Django进阶之Model操作复习 一.字段 AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - ...

  6. 【Python全栈-后端开发】Django进阶1-分页

    Django[进阶篇-1 ]分页 分页 一.Django内置分页 from django.core.paginator import Paginator, EmptyPage, PageNotAnIn ...

  7. 【Python全栈-后端开发】Django入门基础-2

    Django入门基础知识-2 一 .模版 一.模版的组成 HTML代码+逻辑控制代码 二.逻辑控制代码的组成 1  变量(使用双大括号来引用变量) {{var_name}} 2  标签(tag)的使用 ...

  8. 【Python全栈-后端开发】MySQL数据库-练习题

    MySQL数据库-练习题 一.表关系 请创建如下表,并创建相关约束 二.操作表 1.自行创建测试数据 2.查询“生物”课程比“物理”课程成绩高的所有学生的学号: 3.查询平均成绩大于60分的同学的学号 ...

  9. Python 全栈开发 -- 监控篇

    如果你已经玩转了 Python 编程语言语法,肯定想用这些知识,开发一款应用程序,它可以是在网上,可以炫耀或出售,那就需要全栈式开发 Python.具体如何创建,部署和运行生产 Python Web ...

  10. python 全栈开发之路 day1

    python 全栈开发之路 day1   本节内容 计算机发展介绍 计算机硬件组成 计算机基本原理 计算机 计算机(computer)俗称电脑,是一种用于高速计算的电子计算机器,可以进行数值计算,又可 ...

随机推荐

  1. redis未授权访问漏洞——简单记录

    从0复现redis未授权访问漏洞 环境:centos8(ip:10.0.0.3) 安装 redis 工具:kali(10.1.1.136) 1. 介绍 Redis REmote DIctionary ...

  2. knock:端口敲门服务

    knock:端口敲门服务 端口敲门服务,即:knockd服务.该服务通过动态的添加iptables规则来隐藏系统开启的服务,使用自定义的一系列序列号来"敲门",使系统开启需要访问的 ...

  3. Os-hackNos

    Os-hackNos 目录 Os-hackNos 1 环境配置 1.1 靶场环境 1.2 靶机未获取到IP时配置 2 信息收集 2.1 端口扫描 2.2 目录扫描 3 对Drupal 7.57版本安全 ...

  4. 基于Docker部署Dubbo+Nacos服务

    一.说明 本文介绍基于 Docker 部署一套 Dubbo + Nacos 的微服务环境,并解决容器里的 IP 及端口的访问问题. 基于上文<基于jib-maven-plugin快速构建微服务d ...

  5. 用于双目重建中的GPU编程:julia-cuda

    作者:京东科技 李大冲 一.Julia是什么 julia是2010年开始面世的语言,作为一个10后,Julia必然有前辈们没有的特点.Julia被期望塑造成原生的有C++的运行速度.python的易交 ...

  6. nginx中多ip多域名多端口配置

    1.Nginx中多IP配置: server { listen 80; server_name 192.168.15.7; location / { root /opt/Super_Marie; ind ...

  7. Mybatis-概览地图

    思考: "为什么在使用 Mybatis 的时候,只需定义一个接口,不用写实现类就能使用XML中或者注解上配置好的SQL语句,就能完成对数据库 CRUD 的操作呢?" 这是因为用到了 ...

  8. 【win+r】快速打开软件

    第一种设置方法: ①把要启动的文件夹路径添加到系统环境变量里面去 ②按win+r就可以快速启动了 第二种设置方法: 是直接把(程序的)快捷方式,放到安装目录的 Windows\System32\ 文件 ...

  9. RestTemplate 请求

    @Autowired private RestTemplate httpRestTemplate; String code= request.getParameter("code" ...

  10. 8. fitBounds(用了这个你就不用在设置zoom, minZoom, maxZoom, center)

    1 <!DOCTYPE html> 2 <html lang="zh"> 3 <head> 4 <meta charset="U ...