Google 推出 iOS 功能性 UI 测试框架 EarlGrey

  • 张龙

2016 年 2 月 18 日

话题:iOS语言 & 开发

经过了一段时间的酝酿后,Google 很高兴地宣布了EarlGrey,一款针对于 iOS 的功能性 UI 测试框架。诸如 YouTube、Google Calendar、Google Photos、Google Translate、Google Play Music 等多款 Google 应用都成功地采用了 EarlGrey 框架来满足其功能性测试之所需。

EarlGrey 所提供的主要特性如下所示,这些特性使得应用的测试变得更加轻松,也更具效率:

  • 强大的内建同步机制:测试会在与 UI 进行交互前自动等待动画、网络请求等事件。这样,我们就可以更加轻松地编写测试了(无需睡眠,也不必再等待了),同时维护起来也更加容易(非常直观,整个测试看起来就是一系列描述而已)。一般来说,你无需考虑同步性,因为 EarlGrey 会自动同步 UI、网络请求、主 Dispatch Queue 以及主 NSOperationQueue。为了支持在下一个 UI 交互发生前需要等待某个事件出现这种场景,EarlGrey 提供了 Synchronization APIs,你可以通过他们来控制 EarlGrey 的同步行为。你可以使用这些 APIs 来增强测试的稳定性。
  • 可见性检测:所有的交互都发生在用户可以看到的元素上。比如说,尝试轻拍图片后面的按钮会导致测试立刻失败。EarlGrey 使用了屏幕截图区分比较(也叫做“screenshot diffs”)在与 UI 元素交互前确定其可见性。这样,你就可以确定对于 EarlGrey 与之交互的 UI,用户可以看到并且也能与之交互。值得注意的是,进程外(即系统生成的)警告视图与其他会遮盖住 UI 的模态对话框会对这个过程产生干扰。
  • 灵活的设计:用于确定元素选择、交互、断言与同步的组件在设计上就是可扩展的。轻拍与滑动是通过应用级的触摸事件来实现的,而不是使用元素级的事件处理器。在每一次 UI 交互前,EarlGrey 都会断言交互的元素是可见的,而不仅仅是存在于视图层次体系中就行了。EarlGrey 的 UI 交互模拟了真实用户与应用 UI 交互的方式,可以帮助你找到并修复用户在使用应用时所遇到的同样的 Bug。

EarlGrey 是个原生 iOS UI 自动化测试框架,可以帮助你编写出更加清晰、简明的测试。借助于 EarlGrey 框架,你可以使用增强的同步特性。EarlGrey 会自动与 UI、网络请求及各种查询保持同步,同时在必要的情况下,你还可以手工实现自定义的定时器。EarlGrey 的同步特性可以确保在执行动作前,UI 会处于一种稳定的状态。这极大地增强了测试稳定性,使得测试变得高度可重复。EarlGrey 与 XCTest 框架协同工作,并且集成到了 Xcode 的 Test Navigator 中,这样你就可以直接在 Xcode 中或是在命令行中(使用 xcodebuild)运行测试了。

EarlGrey 的用户文档位于 EarlGrey/docs 目录下。要想上手,请先查看一下 EarlGrey 的特性,看看其向后兼容性,然后通过测试目标来安装 / 运行 EarlGrey。配置完毕后,请查看一下 EarlGrey API,然后开始编写自己的测试。

下面来介绍一下如何安装 EarlGrey,以及如何创建并运行第一个测试。

要想正常使用 EarlGrey,请确保被测试的应用满足如下需求:

  • 正确的启动界面图片可以在所有支持的设备上出现(参见 iOS Developer Library,Launch Files)。
  • 主 UIApplicationDelegate 实现了 (UIWindow *)window 属性(参见 UIKit Framework Reference,window 属性)。

最后,请确保在测试目标上启动断言(即不要设置 NS_BLOCK_ASSERTIONS)。可以通过两种方式将 EarlGrey 添加到 Xcode 项目中:使用 CocoaPods,或是以框架的形式。

Cocoapods 安装

对于 EarlGrey 来说,我们强烈推荐使用 CocoaPods 进行安装,这也是我们认为的最佳方式。

第 1 步:创建一个测试目标。

EarlGrey 需要一个测试目标。由于 EarlGrey 修改了测试目标的 Scheme 与 Build 阶段,因此我们建议你为添加 EarlGrey 测试创建一个单独的测试目标。如果还没有创建,那么可以在 Xcode 的 Project Navigator 中选中项目,然后单击菜单中的 Editor > Add Target...。

在 Add Target 窗口中,选择 iOS -> Test -> iOS Unit Testing Bundle:

由于 EarlGrey 使用了 Schemes,因此测试目标必须要有一个与之关联的 Scheme。如果该 Scheme 是共享的就更好了。如果测试目标没有 Scheme,那么请转向 Manage Schemes,单击 + 按钮,然后从下拉菜单中选择目标。选择 Shared 选项,然后将 Container 设为待测试的应用。

值得注意的是,如果之前创建过 Schemes,那么你需要运行一次才能让 pod 安装命令将其选中。如果在运行 pod install 之后,测试目标没有包含对 Scheme 与 Build 阶段的改变,那么请再次运行 pod install。

第 2 步:添加 EarlGrey 并作为框架依赖

创建好测试目标后(比如说 AppFunctionalTests),现在就需要将 EarlGrey 作为框架依赖添加进来了。要想做到这一点,请将 EarlGrey 作为测试依赖添加到 Podfile 中。由于 EarlGrey 必须要放在待测试的应用中,我们需要对测试目标的 Build Phases 与 Scheme 进行一些修改。将 configure_earlgrey_pods.rb 文件添加到项目目录中(在这里运行 pod install 命令)。你需要在 post_install 钩子中调用这个脚本,使用项目名、测试目标名与 xcscheme 文件名。

第 3 步:运行 pod install 命令

当成功运行了 pod install 命令后,打开生成的工作空间,在 Pods/directory 中即可以找到安装好的 EarlGrey。

创建与运行第一个测试

由于 EarlGrey 基于 XCTest,因此在 Xcode 中创建第一个测试就像创建一个新的单元测试用例类一样简单。请不要将 Unit Test Case Class 与 UI Test Case Class 搞混了。UI Test Case Class 使用了添加到 XCTest 中的新的 UI Testing 特性,它与 EarlGrey 并不兼容。

@import EarlGrey
#import 
@interface MyFirstEarlGreyTest : XCTestCase
@end
@implementation MyFirstEarlGreyTest
- (void)testPresenceOfKeyWindow {
 [[EarlGrey selectElementWithMatcher:grey_keyWindow()]
     assertWithMatcher:grey_sufficientlyVisible()];
}
@end
  1. Cmd+Click 应用源文件所在的目录,然后选择 New file...。这时会弹出一个对话框。
  2. 在弹出的对话框中选择 Unit Test Case Class,然后单击 Next。在下一个界面中,输入测试用例的名字。对于该示例来说,我们输入 MyFirstEarlGreyTest。
  3. 在下一个界面中,请确保测试与 Unit Test 目标关联起来。对于该示例来说,目标就是 SimpleAppTests。
  4. Xcode 会为我们创建一个新的测试用例,不过这个用例我们用不上。我们来修改其代码,只留下一个测试方法,并包含进 EarlGrey 框架。
  5. 现在来添加一个简单的 EarlGrey 断言,检查一个 key window 是否存在,并断言它会显示出来。下面就是最终的测试代码:
  6. 就是这些了!就像其他单元测试一样,该测试会显示在测试导航器中,因此可以单击 run 图标或是 Cmd+clicking 测试名,然后选择 Test “testPresenceOfKeyWindow”来运行测试。由于这是个常规的单元测试,因此可以在测试与应用代码中打断点,也可以无缝使用内建工具。

想要试一下 EarlGrey 么?EarlGrey 目前已经开源,并且基于 Apache 许可。感兴趣的读者可以看看这份上手指南,然后通过CocoaPods或是手工的方式将 EarlGrey 添加到 Xcode 的项目文件中。

iOS语言 & 开发