iOS UI 自动化测试原理以及在 Trip.com 的应用实践

2,270 阅读22分钟

前言

笔者入职 Trip.com 已满一年,回顾这一年的工作历程,约一半的时间都在做 UI 自动化测试相关内容。从而,笔者更深入地研究了 iOS 平台下的自动化测试技术,目前也在负责部门 App 自动化测试平台的搭建和维护。故想借这篇文章一并将所踩过的坑以及学习到的技术,系统且全面地整理出分享给大家。

本文的内容大致如下:

  • iOS/macOS UI 自动化测试框架 XCUITest 原理详解
  • 基于 Web Service 的自动化测试平台架构设计
  • AppiumMacaca 介绍与对比
  • Trip.com App UI 自动化测试现状

自动化测试可以分为白盒测试、黑盒测试以及灰盒测试,本文主要围绕 Apple 官方提供的 XCUITest 测试框架,逐步阐明 iOS 操作系统下的 UI 自动化测试原理、架构设计思想以及应用场景。

XCUITest 原理详解

iOS UI自动化测试核心技术

2015 年,Apple 发布了 UI 自动化测试框架 XCUITest 并集成在 Xcode7 中,而 iOS/macOS UI 自动化测试依赖两个核心技术: XCUITestAccessibility

core-technology

XCUITest 是集成在 Xcode 中的测试框架,若想使用 UI 测试功能,可以在创建 iOS 项目时勾选 Include Tests 选项,从而使项目具备自动化测试的能力。而 Accessibility 技术,则是 Apple 官方为视障用户提供的一整套使用 iOS/macOS App 的解决方案。

Xcode 项目创建 UITests Target 并运行测试,其编译产物 Test App 本质上是一个 Deamon 守护进程,该进程有独立的应用程序生命周期,依靠 XCUIApplication 类型进行管理。 UITests 的 Test App 进程在运行时会驱动 Host App(项目的主 Target 产物),并且利用元素审查的相关 API 驱动 Host App 模拟用户行为交互,从而进行 UI 自动化测试。

对于 Accessibility 技术,开发人员需要注意的是,XCUITest 框架默认并不能将所有视图元素审查到,只会审查到可以被 VoiceOver 功能读取文字的元素。比如,UIButtonUILabel,这些视图对于视障用户而言可以通过语音来获知其内容,而对于 UIImageViewUIView 这种对于视障人士并不友好的 UIKit 视图元素默认是不会审查到的,所以编码时要另行配置 Accessibility 相关属性,以保证其支持 Accessibility 从而在 UI 自动化查询的元素层级中可见。

基于 XCUITest 框架 和 Accessibility 技术的自动化测试,有利于 App 进行数据一致性校验,但 UI 一致性校验能力较弱。比如,App 可以针对某些数据请求结果或者某个元素是否存在进行校验,而视觉展示效果却仍需要人工介入。

XCUITest 框架结构

XCUITestAPI

XCUITest 测试框架 API 主要包含:元素查询(UI Element Queries)相关类型,如 XCUIElementQuery,UI 元素(UI Elements)相关类型,如 XCUIElement,以及测试 App 生命周期类型(Application Lifecycle)类型,如 XCUIApplication

接下来,我们创建一个简单 Demo 项目,来学习如何使用 XCUITest 框架编程,并进行 iOS UI 自动化测试。

利用 Xcode UITests Target 进行自动化测试

integrate-tests

创建一个 Demo 工程,勾选 Include Tests 选项,在 ViewController 里编写如下代码。本文 Demo 工程可访问链接 github.com/niyaoyao/UI…

import UIKit

class ViewController: UIViewController {
    lazy var testImageView: UIImageView = {
        let testImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        testImageView.backgroundColor = .red
        testImageView.accessibilityIdentifier = "test imageview"
        return testImageView
    }()
    lazy var testLabel: UILabel = {
        let testLabel = UILabel(frame: CGRect(x: 0, y: 130, width: 100, height: 20))
        testLabel.backgroundColor = .green
        testLabel.text = "test label"
        return testLabel
    }()
    lazy var testView: UIView = {
        let testView = UIView(frame: CGRect(x: 0, y: 170, width: 100, height: 50))
        testView.backgroundColor = .blue
        testView.accessibilityIdentifier = "test view"
        return testView
    }()
    lazy var testButton: UIButton = {
        let testButton = UIButton(frame: CGRect(x: 0, y: 230, width: 100, height: 50))
        testButton.backgroundColor = .yellow
        testButton.setTitle("测试按钮", for: .normal)
        return testButton
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(testImageView)
        view.addSubview(testLabel)
        view.addSubview(testView)
        view.addSubview(testButton)
    }
}

源码解释,上面的这段代码创建了四个视图实例,分别为 UIImageViewUILabelUIViewUIButton 类型,并将四个视图实例添加到当前页面中。其中,UILable 和 UIButton 仅设置了frame、字符串、背景颜色等属性,但是对于 UIImageView 和 UIView 视图除了一般的视图属性,还设置了 accessibilityIdentifier 个属性是为了让 UIImageView 和 UIView 支持 Accessibility 功能,但仅设置这个属性并不能使这两个视图在 Accessibility 的元素层级结构中可见。接下来就对 Accessibility 功能做简要介绍。

让 App 支持辅助功能

使用 Accessibility Inspector

前文中提到 Apple 对于视图元素会默认审查能够通过 VoiceOver 播放文字的视图元素,而对于 UIImageView、UIView 这种默认不支持 Accessibility 功能的需要配置相关特性,而开发人员在开发过程中可以通过 Accessibility Inspector 查看不同进程的 Accessibility 元素层级,该应用可以审查 iOS 和 macOS 的元素。

accessibility-inspector

选择 Xcode 的图标菜单并选择 Open Developer Tool 选项,点击 Accessibility Inspector 即可开始使用。

accessibility-hierarchy

当我们没有设置 isAccessibilityElement 属性时,在 Accessibility 元素层级结构中就无法看到 UIImageView 和 UIView 元素,只能看到 “test label” 和“测试按钮”。而当我们将 UIImageView 和 UIView 的 isAccessibilityElement 属性设置为 true 时, UIImageView 和 UIView 元素才能在元素层级中可见。

accessibility-hierarchy

Accessibility 相关属性
UIAccessibility: var accessibilityLabel: String? { get set }

accessibilityLabel 属性可以解决绝大部分的 Accessibility 问题,当光标将焦点放在设置该属性的元素师时,它的内容可由 VoiceOver 读取的人类可读的字符串。但如果不是需要被视障用户获知的视图元素,仅用于自动化测试,就可以不用设置该属性。

UIAccessibility: var accessibilityIdentifier: String? { get set }

accessibilityIdentifier 属性不会被 VoiceOver 诵读,而是面向开发人员的字符串,可在不希望用户操作 accessibilityLabel 的情况下使用。

UIAccessibility: var isAccessibilityElement: Bool { get set }

如果 isAccessibilityElement 未设置为 true,那么这个视图将不会在 Accessibility 视图层次结构中可见。

The default value for this property is false unless the element is a standard UIKit control, in which case, the value is true. —— Apple Documentation

另外,根据 Apple 官方中的介绍 UIControl 的子类的 isAccessibilityElement 属性都默认设置为 true。

手动编写测试 case

import XCTest

class UITestDemoUITests: XCTestCase {

    override func setUpWithError() throws {
        // ...
    }

    override func tearDownWithError() throws {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
    }

    func testExample() throws {
        // UI tests must launch the application that they test.
        let app = XCUIApplication()
        app.launch()
        let label = app.staticTexts["test label"]
        XCTAssertTrue(label.exists)
        let button = app.buttons["测试按钮"]
        XCTAssertTrue(button.exists)
        let imgview = app.images["test imageview"]
        XCTAssertTrue(imgview.exists)
        let view = app.otherElements["test view"]
        XCTAssertTrue(view.exists)  
        // Use recording to get started writing UI tests.
        // Use XCTAssert and related functions to verify your tests produce the correct results.
    }

    func testLaunchPerformance() throws {
        if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
            // This measures how long it takes to launch your application.
            measure(metrics: [XCTApplicationLaunchMetric()]) {
                XCUIApplication().launch()
            }
        }
    }
}

源码解释,XCUIApplication 类型的实例,是管理 Test App 生命周期的实例对象,可以通过该对象获取 Accessibility 视图层级结构,通过 XCTAssertTrue 断言元素是否存在。

录制交互行为自动生成测试 case

对于相对复杂的 Test Case,可以通过 Xcode 提供的测试行为录制功能进行自动代码生成。

execute-test execute-test

UITest 执行过程

execute-test

点击 Test 定义的 function 前方对应的播放按钮或者 Test Navigator 中对应 function 的播放按钮,就可以开始执行 UI 测试。而开始 UI 测试后,会先执行源码编译,将 Target 中的源码编译出产物,启动 Test App 进程,进入 Test 程序执行 app.launch() 则会启动 App,然后执行断言源码。

iOS 自动化测试工具链

编写了基本的 UI 测试的 UITest Target 方法之后,我们可以利用相关命令行工具链,将 iOS UI 自动化测试脚本化,从而可以方便集成入 CI 流程。

xcodebuild

xcodebuild test -project UITestDemo.xcodeproj -scheme UITestDemoUITests -destination 'platform=iOS,id=<iPhoneUDID>'

可以利用上述命令执行自动化测试,也可以将命令进行拆分,拆分为测试编译命令和测试执行命令,以便细化自动化测试过程。 测试编译命令:

xcodebuild build-for-testing -project ****.xcodeproj -scheme **** -configuration Debug -sdk iphonesimulator -destination 'platform=iOS Simulator,id=XXXXX' -derivedDataPath ~/derived_path -quiet COMPILER_INDEX_STORE_ENABLE=NO GCC_WARN_INHIBIT_ALL_WARNINGS=YES | tee build.log

测试执行命令:

xcodebuild test-without-building -xctestrun ****.xctestrun -configuration Debug -sdk iphonesimulator -destination 'platform=iOS Simulator,id=XXXXXX' -derivedDataPath ~/derived_path -resultBundlePath ****.xcresult -only-testing:****-UITests/TargetTests

xcrun simctl

simctl 命令是 xcrun 的一套自命令,提供一系列用来控制 iOS 模拟器的命令。

列举当前已经启动的模拟器 xcrun simctl list devices | grep booted

启动模拟器 xcrun simctl boot XXXXX

关闭模拟器 xcrun simctl shutdown XXXXX

设置模拟器权限 xcrun simctl privacy XXX grant location-always xx.xx.xxx

安装 App xcrun simctl install {} {}'.format(uuid, app_path)

运行指定 App xcrun simctl launch {} {}'.format(uuid, bundle_id)

结束指定 App xcrun simctl terminate {} {}'.format(uuid, bundle_id)

卸载指定 App xcrun simctl uninstall {} {}'.format(uuid, bundle_id)

ideviceinstaller

与控制模拟器相似,iOS 真机也有相应的控制命令行工具链,例如 ideviceinstaller

安装 apppath 下的 app ideviceinstaller -i apppath

安装 xxx.ipa 为应用在本地的路径ideviceinstaller -u [udid] -i [xxx.ipa]

卸载应用 ideviceinstaller -u [udid] -U [bundleId]

查看设备安装的第三方应用 ideviceinstaller -u [udid] -l

同上,查看设备安装的第三方应用 ideviceinstaller -u [udid] -l -o list_user

查看设备安装的系统应用 ideviceinstaller -u [udid] -l -o list_system

查看设备安装的所有应用 ideviceinstaller -u [udid] -l -o list_all

列出手机上所有的用户安装的app ideviceinstaller -l

ios-deploy

查看当前链接的设备 ios-deploy -c

安装APP ios-deploy --[xxx.app]

卸载应用 ios-deploy --id [udid] --uninstall_only --bundle_id [bundleId]

查看所有应用 ios-deploy --id [udid] --list_bundle_id

查看应用是否安装 ios-deploy --id [udid] --exists --bundle_id

利用以上命令行工具链,就可将 UI 自动化测试根据不同项目进行自定义的脚本接入 CI 流程,比如接入 GitLab Pipelines 中,对 code review、 merge request 等过程进行干预。

基于 Web Service 的架构设计

App 自动化测试平台的架构设计

从前文中我们了解到,我们可以利用 Xcode 创建 UITest Target,编写 UITest Case 测试脚本,辅以 xcodebuild 等相关命令工具链编写自动化脚本,就能接入 CI/CD 流程,实现 iOS App 的 UI 自动化测试,从而达到释放人力资源,降低人工测试的成本的目的。

但与此同时,又有新的问题出现,那就是业务频繁的迭代的情况下,我们写的 Test Case 脚本,很容易因为业务的改变而导致废弃,测试脚本复用率低,又增加了开发成本。如果不同系统平台的 App,如,Android、iOS 甚至 Web App 能共用一套测试脚本,提高脚本复用率,会降低开发成本,更有利于业务回归。

除此之外,对于复杂业务的回归测试,若希望提高大量测试 case 的业务回归效率,必然要提高并发性,缩减测试时间。故在这样的需求下, Facebook 团队就设计出了 Appium 这样的基于 Web Service 的自动化测试工具。类似 Appium 的测试工具还有阿里巴巴团队设计的 Macaca,这类测试工具的设计架构如下图可视。

execute-test

基于 Web Service 的自动化测试的架构主要可以分为命令分发服务 Web Service 模块和 UI 测试驱动模块。

对于命令分发服务模块,其任务是搭建通用测试 case 脚本与底层驱动之间的通信桥梁,而 HTTP RESTful API 恰能满足这样跨平台的需求。因此,Web Service 模块需要搭建 HTTP Web Service 进行命令转发,将自动化测试中的 Test Case 脚本作为 Web Service 的 Client 端,向 Web Service 的 Server 端发送请求。而 Web Service 的 Server 接收到请求后,再将请求转发到底层的 UI 测试的驱动进程,以便后续驱动 UI 测试。

对于 UI 测试驱动模块,其主要任务是,接收 Web Service Server 端转发来的请求,并触发驱动进程进行 UI 自动化测试,最终收集测试结果,并生成测试报告。Android 操作系统的底层驱动一般是 UIAutomator 程序;而对于 iOS 系统, Appium 用的是 WebDriverAgent,Macaca 是 XCTestWD。而不论 WebDriverAgent 还是 XCTestWD 都是一个基于 XCUITest 的 Xcode project,其技术核心也就是我们前文介绍的以 XCUITest 和 Accessibility 为基础的 iOS UI 自动化测试技术。

App 自动化测试平台,需要先运行 Web Service Server,Server 作为测试指令的发出者,向测试驱动发出请求,从而驱动 Test App 进程操作 App。因此,需要先在 Jenkins Slave 机器启动运行 Web Service Server,例如,在本地 4722 端口创建 Web Service,并监听 Client 向该端口发送的请求,再转发给驱动层。

驱动项目(WebDriverAgent 或 XCTestWD)编译成功后,都会在运行的设备上创建并运行一个 Runner 程序,该程序就是利用 XCUITest 编译成 Test App,但与前文 Demo 不同的是,这个程序会在设备上也会创建一个 Web Service,接收 Server 发来的请求,并根据 Test App 中程序处理请求,最后返回响应结果给 Server。

例如,创建测试 Session 过程,WebDriverAgent 编译成功后会在测试设备的 8080 端口创建 Web Service,从而 Jenkins Slave 上运行的 Web Service Server 能够将 Client 的请求转发给 WebDriverAgent 创建的 Web Service,然后经过 WebDriverAgent 的内部路由/wd/hub/session 进行映射,找到对应创建 session 的具体代码,保存 Session ID 值,并将 Session ID 作为响应结果返回给 Jenkins 的 Web Server。其他测试操作如,查找 element、查找元素 value,滚动某个元素等操作,这些操作 Jenkins 的 Web Service C/S 和底层驱动间的通信过程,都与建立 Session 过程相类似。

所以,有了基于 Web Service 的 UI 自动化测试工具,我们可以更加高效地进行自动化测试,复用性更高、可支持多平台,跨平台测试,甚至可以利用其 Web Service 搭建分布式的测试平台,基于 Jenkins 服务的架构设计如下图所示。

execute-test

根据上图架构设计,我们可以利用多台机器搭建 Jenkins 集群,根据我们 CI/CD 流程所需,向 Jenkins Server 发送请求,再由 Jenkins Server 分配不同 Jenkins Slave 执行 Job,每个 Jenkins Slave 都配置好 UI 自动化测试平台驱动多台设备进行自动化测试。从而实现分布式的自动化测试平台,提高并发性、提升测试效率,缩减回归测试的时间。

接下来就分别介绍 Appium 和 Macaca 的简单使用。

Appium 工具链矩阵

WebDriverAgent

WDA 是 Facebook 基于 XCUITest 测试框架开发的 iOS UI 自动测试 Driver。类比 Macaca Runner。

源码安装 WDA
git clone https://github.com/appium/WebDriverAgent.git
真机测试修改 Team ID

选择 Apple 开发账号的 Team。

Appium Web Service Server

Appium Server 用于 HTTP 命令转发,驱动底层 Driver WDA。

利用 Appium Desktop 启动 Server

下载链接 github.com/appium/appi…

安装 Appium App,并用 GUI App 启动 Server。

利用 Appium Command 启动 Server
安装 Nodejs 依赖

执行命令行

npm install -g appium
启动 Server

执行命令行

appium -a 127.0.0.1 -p 4722

参数列表:appium.io/docs/en/wri…

端口映射

执行命令行

iproxy [LOCAL_TCP_PORT] [DEVICE_TCP_PORT]

manpages.ubuntu.com/manpages//t…

github.com/libimobiled…

端口映射关系

执行命令行

appium -a 127.0.0.1 -p 4722 --webdriveragent-port 8123

如果启动 appium server 时设置了 WDA 的 Port 为 8123,则 iproxy 命令第一个入参须是本地监听端口可任意随机选择,第二个入参必须对应 appium 命令指定的 WDA 的端口,可如下执行

iproxy 8100 8123
驱动 Runner 存储位置

全局安装 appium server 到本地后,WebDriverAgent.xcodeproj 存储在以下路径中。

/usr/local/lib/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj

Web Service Client —— Test Case

测试项目

github.com/appium/appi…

javascript-webdriverio
安装依赖

执行命令行

cd appium-master/sample-code/javascript-webdriverio
npm install
修改配置

修改测试脚本中 capabilities 配置。

const iosCaps = {
  platformName: 'iOS',
  automationName: 'XCUITest',
  deviceName: process.env.IOS_DEVICE_NAME || 'iPhone',
  udid: 'iphone udid',
  platformVersion: process.env.IOS_PLATFORM_VERSION || '13.6.1',
  noReset: true,
  bundleId: 'your app id',
  app: undefined // Will be added in tests
};

capabilities 文档 appium.io/docs/en/wri…

appium.io/docs/en/wri…

运行 Case

执行命令行

npm test

Macaca 工具链矩阵

与 Appium 相类似,Macaca 的工具链矩阵也包含 DriverWeb Service ServerWeb Service Client

安装 Macaca 工具链

# 本地安装
$ npm i macaca-ios --save-dev
# 全局安装
$ npm i macaca-ios -g
# 安装有 TEAM_ID 的 macaca-ios
$ DEVELOPMENT_TEAM_ID=TEAM_ID npm i macaca-ios -g

更多详细安装过程可参阅官方文档 macacajs.github.io/zh/guide/en…

Appium 与 Macaca 的对比

框架名称相同点不同点
Appium基于 XCUITest 和 Accessibility 设计的 iOS UI 自动化测试技术驱动项目利用 Objective-C 编写,社区更完善,项目更新迭代更活跃,用户数量更多。
Macaca基于 XCUITest 和 Accessibility 设计的 iOS UI 自动化测试技术驱动项目利用 Swift 编写,社区生态相对不完善,维护较不活跃,用户量相对较少。

我们的 UI 自动化测试平台最初仅接入 Macaca 框架,独立维护一份仓库以供内部平台使用。而维护过程中也会遇到各种问题并自行解决,验证无误后也会反馈给官方,并提供相应解决方案。目前也已开始逐步接入 Appium 框架对现有平台进行技术改造,以适应更多场景,以及保障框架长期稳定可持续地维护。

Trip.com App 自动化测试现状

Trip.com App 在日常开发迭代过程中, UI 自动化测试的应用场景有很多,例如冒烟测试、探索测试,以及基于 Web Service 的 UI 自动化测试平台。接下来,向大家分别介绍不同测试在 CI/CD 中扮演的角色和作用。

应用场景

冒烟测试

基本概况

在程序设计和软件测试领域 , 冒烟测试 (也包括信心测试 、健全性测试、 [1] 构建验证测试 ( BVT ) [2] [3]、构建验收测试 )是指初步地进行测试,并以此展示一些简单但足以影响发布软件版本的这一高级别的错误。 —— Wikipedia

在 Trip.com 实际应用场景中,冒烟测试所担任的角色主要是 Merge Request 卡点检测,其主要作用是对 Trip.com App 的集成编译以及运行时闪退的预先校验。比如,对于多模块并行开发的情况下,不同团队的某些改动就会造成符号名找不到的问题,而冒烟测试就可以预先对此进行卡点,避免集成打包失败降低试错成本和时间成本。

而对于 Trip.com iOS 的冒烟测试具体实践,就是在主项目中创建 UITest Target 编写简单的 UI 视图校验程序,并接入 GitLab Runner Pipeline,利用 xcodebuild 工具链对编译过程和运行时健壮性进行初步校验,以保证合入主分支的代码,不会使 App 出现明显的重大闪退等问题。

数据体现

冒烟测试在 Trip.com 快速迭代开发的过程中,作为 Merge Request 的卡点任务,利用多台 GitLab Runner 实现并发执行六个冒烟测试任务,大大缩减了卡点校验的时间,单个冒烟测试时间控制在 6min 之内,不仅达到了验证集成包的编译构建和健壮性的目的,还大大节省了测试验证的时间成本。

探索测试

基本概况

探索性测试(Exploratory Testing)是软件测试方法的一种,它的特点为在进行测试时,同时探索开发更多不同型态的测试方式,以便改善测试流程。 —— Wikipedia

探索测试在 Trip.com App 实际应用场景中,主要担任的角色是 App 页面随机测试,主要用于验证集成打包 App 的质量,随机点击页面,并收集和统计 Page View 以及 Crash 数据,最终整理成报告发给相关开发同学。

exploretest

Trip.com iOS 探索测试是基于 Google eDistantObjectEarlGrey 开源项目开发的白盒/灰盒 UI 测试框架。区别于 XCUITest 编写 Test Case 并且必须结合 Accessibility 的测试方式,白盒/灰盒的探索测试框架,则是利用 Test App 和 Host App 进程间通信,使 Test App 驱动 Host App 进行 UI 自动化测试,而 App 的元素审查、用户交互以及数据收集则都是在 Host App 进程中完成。 没有了 Accessibility 的限制,白盒/灰盒的探索测试元素审查更全面,稳定性更高,测试数据也相应更全面。

数据体现

Trip.com 探索测试是用于验证 App 集成包稳定性的日常 Jenkins 任务,收集全部触达页面,可有效预先发现 Crash 问题,并发送测试结果的报告邮件给研发组。iOS 的探索测试在并发数为 5 的情况下,2 小时测试有效触达非重复页面可达 180 个,场景涉及首页 Feed 流、玩乐旅拍、订单页面等场景。探索测试收集的 Crash 问题,会收集崩溃调用栈整理成表格,分配给相关研发同学,推动产线修改相关问题代码。

UI 自动化测试平台

基本概况

Trip.com App UI 自动化测试平台,是由 IBU 公共测试团队和 IBU 公共无线共同设计搭建的可视化、数据统一管理的质量保证平台。在 App 快速迭代的开发过程中,为提高测试效率,利用多台机器,搭建 Jenkins 集群,实现用例并发执行 Case,进行 App 回归测试,减少人力测试成本,并将测试问题报告反馈给相关开发同学,推动开发同学完善功能,从而,保证 App 上线前的质量。而选用的测试框架主要是 Macaca,并且将逐步向 Appium 迁移改造。

数据体现

UI 自动化平台目前处于开发的一阶段,日常回归测试中,对于复杂业务场景的测试,机器性能稳定且并发数目 6 的情况下,测试总耗时可控制在 40 分钟,测试总用例数可达 209 个,Step总数 3077 步,Feature 通过率达 97.14% ,Case 通过率达 98.56%

以上不同的自动化测试应用实践,接入不同的 CI/CD 流程中,都为 Trip.com App 快速开发迭代过程中提供了质量保证。

总结

对于 iOS 平台下的 UI 自动化测试技术,Apple 官方提供的两个核心技术是 XCUITestAccessibility。而为了能够增强复用性,更利于分布式进行自动化测试,不同厂商又在此基础上设计实现了基于 Web Service 的自动化测试平台,优点是具有易部署、跨平台等特性,可以更大程度上利用分布式增强并发性,提高测试效率,减少人力测试成本。

当然,市面上 UI 自动化框架还有很多,例如 STF 和 Airtest,这类框架底层驱动利用图形图像识别进行 App 元素的定位。而对于目前 Trip.com iOS 的自动化测试应用实践,则更多是基于 XCUITest 框架实现的,所以本文暂不讨论此类测试框架。但不论何种驱动进行 App 的自动化测试,整体的架构设计都会以文中介绍的 Web Service 进行设计,以达到跨平台、易集成、高复用等目的。

特别鸣谢

感谢读到本文最后的你,当然除了感谢耐心读完文章的每一位读者,我还想感谢我们 Trip.com IBU 公共无线团队的每一位小伙伴,尤其感谢我的 leader 郭耀家(Shanks) 同学 :D。

在我加入 IBU 大家庭的这一年多的时间中,Shanks 对我足够的信任,放手让我尝试各种不同的项目。从入职到现在,我参与了诸如,编译打包时间优化、支持 Swift Coverage 增量覆盖率,CI/CD 流程自动化提升,以及 UI 自动化测试等一系列我之前从未接触过的技术,使我个人在这一年的时间里,技术水平有了迅猛提升,眼界也更开阔。在工作的过程中,我如果遇到很困难的问题,也可以和 Shanks 沟通交流,从而获得不同的解决思路。除此之外,Shanks 也没有给我施加过大的心理压力,只要最终结果能符合预期,即便过程并不顺畅也不会对我有过多苛责。所以,衷心感谢香克斯同学对我的帮助,也祝 Shanks 一切顺利、天天开心。

在 IBU 工作的一年多时间是相当愉快的,而 IBU 公共无线团队也是是我从业至今感觉最喜欢、最欢乐的团队。所以,这篇文章也是我给团队的一份答卷,如果自己给这一年多的成长和成果打分,我感觉我能得 75 分吧。所以很感谢现在的团队给我尝试和挑战的机会,我也很珍惜和团队里每一位小伙伴共同协作的时光,希望今后继续扬帆远航,活到老学到老,归来依旧是少年,加油!

当然,如果此时此刻的你,有意加入我们 IBU 公共无线团队,想和我们小伙伴一起参与质量保证、CI/CD 效率工具等研发工作,欢迎各位能人贤士发送简历到 y_ni@trip.com,期待大神带我飞 😁。

参考资料