UI自动化测试的价值
1、提升回归测试的效率
2、可以进行兼容性测试
UI 自动化测试应用场景
• 冒烟测试自动化:提测之前自动断言提测质量,提供准入参考。
• 功能测试自动化:辅助 QA 与测试工程师的快速验证。
• 验收测试自动化:兼容性测试等。
• 移动端性能专项测试自动化:性能、卡顿、健壮性测试、竞品分析。
测试框架
• 阿里 Macaca
• 腾讯开源微信小程序自动化测试工具
• 百度内部的 Cafe 框架
自动化测试常见误区
强调自动化测试不代表手工测试无用
• 手工测试非常有用,仅有手工测试是不够的。
• 手工测试 + 自动化测试才是企业快速迭代的根基
UI 自动化测试的“瓶颈”
• 技术成本高:
• 人力成本高:优秀测试开发工程师难招
• 技术门槛高:80%的自动化测试工程师在自动化能力上都不及格
• 维护成本高
• 复用率不高:UI 和业务流程变更是最主要变更
• 稳定性不足:容易被干扰,执行慢
• 常见行业错误观点
• 错误观点一:UI 自动化测试无用论
• 错误观点二:UI 自动化测试只能模拟人工
合理地使用 UI 自动化
• 使用分层测试策略,控制 UI 自动化测试规模:
• 少数核心用例交给自动化测试
• 大部分的基础回归测试交给自动遍历
• 新功能测试交给人工测试
• 技术改进方案:
• 良好的维护模型:PageObject、数据驱动
• 更好的框架支持:增加 Watch,智能等待,失败重试等机制
自动化测试就是机器点点点?
• 传统自动化测试
• 自动探索测试 自动化对新功能进行测试?
• codeless 方向的自动化测试 不需要写代码就可以完成自动化测试
• 自动化测试用例智能生成
如何高效实用的落地自动化
• 学习方向
• 了解待测产品和平台:Android、iOS、App
• 精通最好的测试框架:Appium、UI Automator、WebDriverAgent
• 掌握自动化测试落地经验:PageObject、稳定性提升、数据驱动……
• 达到的结果
• 一天搞定一款 app 的自动化测试脚手架
• 一天完成单个功能的业务测试自动化用例集合
• N 周内搞定公司的 app 自动化测试
移动自动化测试的技术体系
UI 自动化分类
• Web 自动化:Selenium
• App 自动化:Appium
• GUI 自动化:Windows、Mac
• 微信小程序自动化:App + Web 测试技术的外延形态
• 更多平台:智能设备、机器人、工业 app
UI 自动化测试方面的成就
• Google:Espresso、UI Automator
• Facebook:WebDriverAgent
• 焰焮ibaba:Macaca
• Ebay:Selendroid
• Walmart:Robotium
• Sauce Labs:Appium
• ThoughtWorks:Selenium
Appium
Appium 的设计理念
Appium client:对应语言的client包和脚本,如python的Appium-Python-Client并编写脚本
Appium server:启动服务开放端口,接收appium client客户端的http请求
driver:appium需要driver来驱动移动端,Appium team目前维护了很多driver,需要根据平台来选择driver。Android平台一般使用Uiautomator2 driver。。IOS使用XCUITest driver
自动化测试框架选择
• 推荐 Appium
• 跨语言:Java、Python、Node.js 等
• 跨平台:Andoid、iOS、Windows、Mac
• 底层多引擎可切换
• 生态丰富,社区强大
• iOS:KIF、WDA、XCTest
• Android:Robotium、UI Automator
• 特色框架:calabash、Macaca、ATX
Appium 引擎列表
• Android
• Selendroid、Espresso [推荐]
• UI Automator、UI Automator2 [推荐]
• iOS
• UI Automation [已废弃]
• XCUITest [推荐]
• 更多平台:Mac、Windows、游戏引擎等
Appium 多端架构与自动化
UI 分层测试体系
移动 App 分层测试
移动 App 快速迭代模型
自动遍历测试与其价值
• 定义:以自动化的方式对 app 进行充分的功能遍历以探索 bug
• 价值
• 降低自动化维护成本,可替代 80% 的自动化测试
• 实现新功能的探索
• 实现老功能的回归
• 用途:多设备兼容测试、自动化专项测试
常见遍历工具与技术
• Android 原生 Monkey
• 百度 SmartMonkey
• 腾讯 New Monkey
• 阿里 Macaca 的 NoSmoke
• TesterHome 社区 vigossjjj smart_monkey
• TesterHome 社区 zhangzhao Maxim
• TesterHome 社区 seveniruby AppCrawler
• Google 出品的 App Crawler
合理的使用 UI 自动化
• 单元测试:使用 App 分层测试策略,增加单测规模,控制 UI 自动化测试规模。
• 移动 App 自动化测试:核心集成与验收测试用例交给自动化测试。
• 自动遍历测试:大部分的基础回归测试交给自动遍历。
• 人工测试:测试团队主负责,整个产品团队参与。
Android app 的常见概念
Android 自动化前提依赖
• Android SDK:Android Studio 可辅助安装
• 模拟器
• Android Studio 自带 Emulator [推荐]
• Genymotion、网易 MuMu、BlueStacks
• 真机
获取 App 的信息
• App 信息
• 获取当前界面元素:adb shell dumpsys activity top
• 获取任务列表:adb shell dumpsys activity activities
• App 入口
• adb logcat |grep -i displayed
adb logcat | findstr Displayed (windows cmd用这个)
• aapt dump badging mobike.apk | grep launchable-activity
• apkanalyzer 最新版本的 SDK 中才有
• 启动应用
Android 调试桥 adb 命令详解
环境准备
• 真机 or 模拟器
• 下载 Android SDK
• 设置 PATH 变量加入 SDK 的工具目录
Android 常用命令
• adb:Android Debug Bridge
• adb devices:查看设备
• adb kill-server:关闭 adb 的后台进程
• adb tcpip:让 Android 脱离 USB 线的 TCP 连接方式
• adb connect:连接开启了 TCP 连接方式的手机
• adb logcat:Android 日志查看
• adb bugreport:收集日志数据,用于后续的分析,比如耗电量
adb shell
• adb shell 本身就是一个 Linux 的 shell,可以调用 Android 内置命令
• adb shell
• adb shell dumpsys
• adb shell pm
adb shell pm clear com.android.contacts
清除包的缓存数据和权限,获得一个比较新的环境。
• adb shell am
• adb shell am start -W -n com.android.contacts/.activities.PeopleActivity -S
• adb shell ps
• adb shell monkey
常用命令列表
• adb
• pm 包管理工具
• am 启动一个APP
• dumpsys 获取整个系统的性能数据
• uiautomator 获取APP的界面结构,执行自动化测试
• input 完成简单的自动化指令
Android 性能统计 dumpsys
• 获取所有的 dumpsys 子命令 dumpsys | grep -i DUMP
• 获取当前 activity adb shell dumpsys activity top
• 获取 activities 的记录,可以获取到 appium 依赖的原始 activity dumpsys activity activities
• 获取特定包基本信息 adb shell dumpsys package com.xueqiu.android
• 获取系统通知 adb shell dumpsys notification
• 获得内存信息 adb shell dumpsys meminfo com.android.settings
• 获取 cpu 信息 adb shell dumpsys cpuinfo
• 获取 gpu 绘制分析 adb shell dumpsys gfxinfo com.android.settings
• 获取短信 adb shell dumpsys activity broadcasts | grep senderName=
uiautomator
• adb shell uiautomator runtest ...
运行自动化测试用例
• adb shell uiautomator dump
adb shell uiautomator dump
把Android APP控件生成xml文件
UiAutomator是测试Android原生态APP的功能测试工具。Android 4.1发布时包含了这种新的测试工具—UiAutomator。UiAutomator用来做UI功能测试的。
uiautomator2是uiautomator的升级版,uiautomator是Google开发的一款用来做安卓自动化测试的Java库。适用于Android4.4+
简单的自动化工具 input 命令
• text (Default: touchscreen)
• keyevent [--longpress] ... (Default: keyboard)
• tap (Default: touchscreen)
adb shell input tap 529 1176
点击屏幕上该坐标
• swipe [duration(ms)] (Default: touchscreen)
• draganddrop [duration(ms)] (Default: touchscreen)
• press (Default: trackball)
• roll (Default: trackbal
Appium 架构介绍
文档:The Context API - Appium Documentation
Appium 生态工具
• adb:Android 的控制工具,用于获取 Android 的各种数据和控制
• Appium Desktop:内嵌了 Appium Server 和 Inspector 的综合工具
• Appium Server:Appium 的核心工具,命令行工具
• Appium Clients:各种语言的客户端封装库,用于连接 appium server
• Java、Python、Ruby、robotframework-appium
• AppCrawler 自动遍历工具
Desktop 主要功能
• UI 分析
• 录制用例
• 元素查找测试
• Attach 已有的 session
• 云测试
python 客户端安装
• 客户端安装:pip install Appium-Python-Client
• IDE:PyCharm
• Python 多版本隔离工具:venv
• 国内依赖源:http://pypi.douban.com/simple/
• 测试框架:unittest、pytest、nose,推荐 pytest
APP自动化
控件定位方法
常用定位手段
• id
• Accessibility ID
• XPath
元素定位
• 测试步骤三要素:
• 定位、交互、断言
• 定位
• ID (重要)
• XPath(重要)
• Accessibility ID: content-desc(重要)
• 不推荐:Class -iOS -Android
常用自动化 API
常见自动化动作支持
• click
• sendKeys
• swipe
• touch action
手势操作 TouchAction
• press release longPress
• tap wait
• moveTo
• perform
capabilities 设置
Capabilities - Appium Documentation
Capabilities是appium启动server会话时设置的参数,告诉server需要启动的APP入口,android版本等信息。
• App APK 地址 appPackage 包名 appActivity Activity 名字
• automationName 默认使⽤ uiautomator2
• noReset fullReset 是否在测试前后重置相关环境
• autoGrantPermissions ⾃动赋予 App 权限
• unicodeKeyBoard resetKeyBoard 是否需要输⼊⾮英⽂之外的语⾔并在测试完成后重置输⼊法
Appium 设备交互 API
可见Appium Python Client 文档Welcome to Appium python client’s documentation! — Python client 1.0 1.0 documentation
常用的设备交付命令
• 模拟电话、短信
用下面的命令模拟 GSM 电话和短信,注意:只能在模拟器上使用!
self.driver.make_gsm_call("5551234567", GsmCallActions.CALL);
self.driver.send_sms('555-123-4567', 'Hey lol')
Original error: gsmCall method is only available for emulators 这里在夜神模拟器上执行是失败的。
• 横竖屏切换
• App 处理
# 实现 APP 的安装
self.driver.install_app('/Users/johndoe/path/to/app.apk')
# 检测 APP 是否被安装
self.driver.is_app_installed('com.example.AppName');
# 启动 APP
self.driver.launch_app()
• 键盘、粘贴板
设置系统剪贴板的内容:
self.driver.set_clipboard('happy testing')
self.driver.set_clipboard_text('happy testing')
获取到剪贴板的内容:self.driver.get_clipboard()
self.driver.get_clipboard_text()
• 录屏
显式等待
• 功能差别
• 显式等待的条件非常灵活
• 隐式等待只用于元素定位
• 执行差别
• 显式等待本地轮询条件
• 隐式等待通过 appium server 轮询条件
def assert_exist_element(self,loc): try: WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(loc)) return True except: print("元素{}不存在".format(loc)) return False
XPath 介绍
• 绝对定位:根据严格的父子关系定位
• 相对定位:根据条件匹配定位
• 慢的原因:XPath 定位比其他定位慢,因为需要递归解析每个元素的属性
• 慢的不明显的原因:有 Cache 机制
常用 XPath 相对定位表达式
• 查找:
• //*[@text='登录’]
• //*[contains(@resource-id, 'login’)]
• 条件匹配:
• //*[contains(@resource-id, ‘login’) and contains(@text, ‘登录’)]]
• //*[contains(@text, ‘登录’) or contains(@label, '登录’)]]
• 寻找所有元素://*
Toast 识别方法
• automationName:uiautomator2
• getPageSource 是无法找到的
• 必须使用 xpath 查找
• 推荐 //*[@class= ‘android.widget.Toast']
• 或者 //*[contains(@text, "xxxxx")]
断言体系
元素是否存在:find_elements
assert len(self.driver.find_elements(by=AppiumBy.XPATH, value='//*[@text="Battery"]'))>=1 #断言存在该元素 assert "哈哈" in self.driver.find_element(by=AppiumBy.XPATH, value='//*[@text="Battery"]').text
• 元素属性正确性:get_attribute
xUint常用断言
传统的xUnit风格的assertXXX()系列
Hamcrest断言,基于更灵活的Matchers断言方式 --推荐 https://github.com/hamcrest/PyHamcrest
参数化与数据驱动
参数化
• 参数化:根据传入的数据,对测试用例进行迭代调用
• 数据驱动:基于数据完成流程调度,通常数据来源自外部数据文件
• 参数化是数据驱动的基础和特例
数据驱动
• 参数化数据读取自外部文件:使用 YAML、JSON 读取
• 测试步骤读取自外部文件:定制执行引擎
• 断言步骤读取自外部文件:定制执行引擎
• 整个用例读取自外部文件:动态创建用例
Native 原生 App 的自动化测试
多种架构支持
Native 原生应用的分类
• Android 标准组件
• 非标准组件:
• Flutter:闲鱼
• React Native:Facebook
• Weex:极客时间
• 游戏
非标准控件的特征
• 非 WebView 组件
• 原生控件可识别
• HTML 控件被编译为 Native 控件
• HTML 的文本属性被解析为 Native 属性
• text 还是 content-desc 取决于 API 版本
常见 Native 自动化测试方式
• Android 原生组件:Appium 默认支持
• Native非标准组件:Appium默认支持
• 自定义 View 识别:
• 使用相对定位,父控件加百分比偏移
• OCR、图像识别、AI
• 游戏控件识别:使用游戏引擎特定技术
游戏自动化测试支持
• Appium 提供了简单的游戏自动化测试支持
• 图像识别
• AI 识别
• 游戏测试的推荐做法
• 提高可测性:编码输出游戏引擎下的控件布局信息,与 Appium 对接
• 使用成熟的 airtest 框架
Hybrid 混合 App 的自动化测试
WebView 控件在 Appium 中的抽象
• Native 层面支持
• uiautomator 解析 WebView 中的内容并映射为原生控件
• getPageSource 为 DOM 结构可发现 WebView 组件和控件
• 切换为 WebView 上下文
• 切换后才是正规的 Web
• getPageSource 为 HTML
• 可以使用 CSS 定位等
Hybrid 测试流程
• 首先进去带有 WebView 的页面
• 使用 Contexts API 寻找 WebView
• 使用 Context 切换到 WebView
• 使用 CSS 等 Web 定位方式
• 使用 Context 重回 Native
真机进行 WebView 测试的前提
• 模拟器默认支持
• 物理机需要打开 app 内开关
• 检测是否打开:反编译检查对应的 API 调用
WebView 测试 - Python
找对 ChromeDriver 的版本
• Android 默认浏览器:
• 老版本 Android 用 Browser,新版本 Android 用 Chrome
• adb shell dumpsys package com.android.webview | grep versionName
• adb shell dumpsys package com.android.chrome | grep versionName
• App 自带 WebView 组件:每个 App 自带的 WebView 的版本也都不相同
Android WebView进程信息
• getContextHandles
• 查看所有的 WebView 进程
• adb shell cat /proc/net/unix | grep webview
• Context 切换
• 把 domain socket 映射为本地的 socket 端口
• adb forward tcp:$port localabstract:webview_devtools_remote_$pid
• 获取对应的 WebView 组件版本 http://localhost:$port/json/version
• ChromeDriver 协议交互
设置 ChromeDriver
• ChromeDriver 安装
• 提前下载所有的 ChromeDriver 版本备用
• 运行时指定
• 隐式选择:1.8版本以后支持自动选择 ChromeDriver
• 显式指定:chromedriverExecutableDir 设置
• 调试开关:
• showChromedriverLog
纯 H5 站自动化测试
浏览器自动化技术原理
浏览器调试工具 DevTools
对网站进行分析
移动浏览器测试 - Python
小程序自动化测试
小程序自动化的三个方法
• 利用 Uiautomator 的原生定位
• 利用微信提供的小程序自动化 SDK
• 基于WebView的测试方法
基于原生定位的方法
• Appium 使用 Uiautomator2 定位可以识别内部 WebView 组件
• 缺点:元素定位符不够精确,content-desc、resource-id 多数都没有
• NoReset 默认为 false,会默认清空微信聊天记录,所以请使用测试机测试帐号
基于微信提供的小程序自动化 SDK
• 使用 Node.js 体系
• 微信小程序自动化 SDK + 标准的测试框架
• 支持真机与 Web 模拟器
微信小程序自动化 SDK 的缺点
• 从官网提供的代码示例来看,微信的这套体系主要用于研发自测
• 微信的研发对自动化测试理解不到位,大量的 wait,实用性不高
• 需要在已有的 WebSocket 体系上做二次封装对接 Appium
• 希望微信可以重视这块的测试支持改进
基于 WebView 的测试方法
• 微信6.x版本支持基于 WebView 自动化测试
• 7.x改版后默认已经无法使用基于 WebView 的自动化
• 7.x + root强行开启 WebView debug + Appium hack
• 曾经这个方案是最好用的,Appium 默认支持
• 但是当前微信版本里这个方法已经被破坏,绕过条件比较苛刻,暂时不可用了
Page Object 模式
做法
• 以页面为单位独立建模
• 隐藏实现细节
• 本质是面向接口编程
• 优点
• 减少重复 find click 样板代码
• 易读性提高
• 页面修改不影响测试用例
Page Object 六大设计原则
登录场景
• 登陆页面提供 login findPassword 功能
• Login 类 + login findPassword 方法
• 登录页面内的元素有多少并不关心,隐藏内部界面控件
• 登录成功和失败会分别返回不同的页面
• findPassword
• loginSuccess
• loginFail
• 通过方法返回值判断登录是否符合预期
编写用例顺序
• 根据界面封装 page 类与方法,实现可以为空
• 编写用例,不断重构明确 page 里方法的入参和返回值
• 开始实现 page 内的方法
• 调试
BasePage 封装
• 实现通用的 Page 方法,对常用自动化行为做封装
• 管理各种 Driver
• 减少每个 Page 对 Appium、Selenium 等库的太多依赖
自动化行为封装
• 异常弹框处理:广告、好评、升级、tips 等弹框
• 通用自动化能力封装
基于 POM 的用例组织结构
• page:完成对页面的封装
• driver:完成对 Web、Android、iOS、接口的驱动
• testcase:调用各类 page 完成业务流程并进行断言
• data:配置文件和数据驱动
• utils:其他便捷的功能封装,可选
测试用例管理
• 用例组织结构:
• 使用 package 管理业务模块
• 使用 class 管理业务对象、使用method完成业务具体行为
• 数据驱动:测试数据、测试步骤、测试断言
• 测试用例:
• 使用 testcase 完成测试步骤的定义
• 使用 assertion 完成业务正确性校验
• 持续集成:使用 Jenkins 完成持续集成