写点什么

构建 iOS 持续集成平台(二)——测试框架

  • 2013-09-17
  • 本文字数:4494 字

    阅读完需:约 15 分钟

测试框架

有了自动化构建和依赖管理之后,开发者可以很轻松的在命令行构建整个项目,但是,作为持续集成平台来说,最重要的还是测试,持续集成最大的好处在于能够尽早发现问题,降低解决问题的成本。而发现问题的手段主要就是测试。在 Martin Fowler 的 Test Pyramid【10】一文中论述了测试金子塔的概念,测试金字塔的概念来自 Mike Cohn ,在他的书 Succeeding With Agile 中有详细描述:测试金字塔最底层是单元测试,然后是业务逻辑测试,如果更细化一点的话,可以分为把完整的测试策略分为如下的层级:

作为持续集成平台,能自动化的测试层级越多,平台就能产生越大的价值。

Unit Test

目前,在 iOS 领域, 最流行的 Unit 测试框架有 2 个:OCUnit【11】和 GHunit【12】,这两个框架各有其优缺点:

优点

缺点

OCUnit

与 Xcode 无缝集成, 快捷键,Scheme 配置都非常方便

1. 只能一次运行整个测试,不能灵活的运行某个测试集 ; 2. 测试结果输出的可读性不好,不容易找到失败的测试

GHUnit

1. 自带 GUI,测试结果清晰可见;2. 可以灵活的运行指定的测试;3. 开源项目

1. 需开发者安装,配置略显复杂;2. 对命令行运行测试的支持不是很好,

OCUnit 的运行结果会通过弹窗直接告诉开发者,运行的细节信息则会打印在 Xcode 的输出窗口中:

GHUnit 的运行结果则全部显示在自己的应用界面中,开发者可以在应用中查看所有的信息,以及做运行测试等各种各样的操作。

关于如何使用 OCUnit 和 GHUnit, InfoQ 上有高嘉峻的文章《iOS 开发中的单元测试》( http://www.infoq.com/cn/articles/ios-unit-test-1)有详细的介绍,我就不再这儿重复叙述了。

如果单从单元测试框架来看,个人更喜欢 GHUnit 测试结果的可读性和运行测试的灵活性,但是,随着 Facebook 的 xctool 的发布,OCUnit 华丽丽的逆袭了,因为 xctool 帮助 OCUnit 把运行测试的灵活性和测试结果的可读性这两块短板给补齐了,再加上其和 Xcode 的集成优势以及通过命令行运行的便捷性,让其成为持续集成平台的 Unit 测试框架的首选。

在 Java 程序员的心中,Junit 和 Hamcrest 永远是一体的,Hamcrest 为 junit 提供了非常丰富的断言机制,极大的增强了测试的可读性。越来越活跃的 iOS 开发社区,当然不会让 Object-C 的世界缺失这样一个优秀的框架,于是 OCHamcrest【13】诞生了。

在测试项目中使用 OCHamcrest 非常简单,尤其是使用了 cocoapods 管理依赖的项目。只需要在 Podfile 文件中加上:

复制代码
target :<TestTargetName> do
...
pod 'OCHamcrest'
end

然后,运行“pod install”命令安装 Hamcrest 到测试 Target,安装好之后,为了在测试类中使用 OCHamcrest 的断言。还需要在测试类的头文件中加入如下代码:

复制代码
#define HC_SHORTHAND
#import<OCHamcrest/OCHamcrest.h>

开发者可以把这段代码加入-prefix.pch 中,这样所有的测试类就都可以使用 OCHamcrest 的断言了。在前面提到的高嘉峻的文章中的第二部分更加详细的讲解了 OCHamcrest 的断言,以及其和另一个断言框架 Expecta 的对比,感兴趣的同学可以跳过去看看( http://www.infoq.com/cn/articles/Matching-Engine-Enliven-Assertion-2?utm_source=infoq&utm_medium=related_content_link&utm_campaign=relatedContent_articles_clk )。

Component Test & Integration Test

在开发手机应用时,总难免会和其他的系统集成,尤其当开发的应用是某个系统的手机客户端时,这样就涉及到很多第三方 API 的集成点需要测试,在成熟的 Java 世界中,诞生了 EasyMock,Mockito,moco 等针对这种集成点的测试工具。同样的,活跃的社区力量正一步一步的在让 Object-C 世界成熟,OCMock【14】诞生。

OCMock

有了 cocoaPods,新加框架变得非常容易,基本上就是“哪里没有加哪里”的节奏,添加 OCMock 框架,只需要在 Podfile 文件中加上:

复制代码
target :<TestTargetName> do
...
pod 'OCMock', '~> 2.0.1'
end

然后,运行“pod install”命令安装 OCMock 到测试 Target,同样的,需要把 OCmock 的头文件添加-prefix.pch 文件中

复制代码
#import<OCMock/OCMock.h>

下面是一个简单的使用 OCMock 的例子,更多的用法请参考 OCMock 的官网: http://ocmock.org/features/:

复制代码
- (void)testSimpeMockPass{
idmockObject = [OCMockObjectmockForClass:NSString.class];
[[[mockObject stub] andReturn:@"test"] lowercaseString];
NSString * returnValue = [mockObjectlowercaseString];
assertThat(returnValue, equalTo(@"test"));
}

moco

moco【15】以其对系统集成点测试的贡献荣获了 2013 年的“Duke’s Choice Award”奖,虽然其以 Java 写成,主要的生态系统也是围绕 Java 打造,但是,其 Standalone 模式可以非常方便的构造一个开发者期望的服务器,这对于 Mobile 领域的集成点测试来说,本就是一个非常好的 Mock 服务器的工具。Moco 有如下的特点:

  • 易于配置,使用:一个 Json 配置文件,然后“java -jar moco-runner–standalone.jar -p 8080 ***.json”就可以启动一个 Mock 服务器。该服务器的所有行为都在配置文件里。如果你想添加,修改服务器行为,只需要修改一下配置文件,然后重新启动该服务器就行了。
  • 配置文件可读性好,使用 Json 格式的配置文件,对绝大多数开发者来说都可以很容易理解。
  • 支持模拟客户端需要的所有 http 操作,moco 实现了针对请求 Content、URI、Query Parameter、Http Method、Header、Xpath 的模拟。对响应的格式支持有 Content、Status Code、Header、URL、甚至支持 Sequence 请求,即根据对同一请求的调用次数返回不同的结果。
  • 完全开源,代码不多也比较易懂,如果没有覆盖到我们的场景,完全可以在该项目基础上实现一个自己的 Mock 服务器 。

熊节在 infoQ 上发表的《企业系统集成点测试策略》【16】一文中,详细的论述了在企业系统中,moco 对测试系统集成点的 帮助。这些论点在 Mobile 开发领域同样适用,因此合理的使用 moco 可以帮助 iOS 开发者更加容易的构建一个稳固的持续集成平台。

System Test

对于 iOS 的系统(UI)测试来说,比较知名的工具有 UIAutomation【17】和 FonMonkey【18】。

UIAutomation

UIAutomation 是随着 iOS SDK 4.0 引入,帮助开发者在真实设备和模拟器上执行自动化的 UI 测试。其本质上是一个 Javascript 的类库,通过 界面上的标签和值的访问性来获得 UI 元素,完成相应的交互操作,从而达到测试的目的,类似于 Web 世界的 Selenium。

通过上面的描述,可以得知,使用 UIAutomation 做测试时,开发者必须掌握两件事:

  • 如何找到界面上的一个 UI 元素
  • 如何指定针对一个 UI 元素的操作

在 UIAutomation 中,界面就是由一堆 UI 元素构建的层级结构,所有 UI 元素都继承对象 UIAElement ,该对象提供了每个 UI 元素必须具备的一些属性:

  • name
  • value
  • elements
  • parent

而整个界面的层级结构如下:

复制代码
Target(设备级别的 UI,用于支持晃动,屏幕方向变动等操作)
Application(设备上的应用,比方说 Status Bar,keyboard 等)
Main window(应用的界面,比方说导航条)
View(界面下的 View,比方说 UITableView)
Element(View 下的一个元素)
Child element(元素下的一个子元素)

下面是一个访问到 Child element 的例子:

复制代码
UIATarget.localTarget().HamcrestDemo().tableViews()[0].cells()[0].elements()

开发者还可以通过“UIATarget.localTarget().logElementTree()”在控制台打印出该 target 下所有的的 elements。

找到 UI 元素之后,开发者可以基于该 UI 元素做期望的操作,UIAutomation 作为原生的 UI 测试框架,基本上支持 iOS 上的所有 UI 元素和操作,比方说:

  • 点击按钮,例: ***.buttons[“add”].tap()
  • 输入文本, 例:***.textfields[0].setValue(“new”)
  • 滚动屏幕,例:***.scrollToElementWithPredicate(“name begin with ’test’”)
  • ……

关于使用 UIAutomation 做 UI 测试,推荐大家一定要看一下 2010 的 WWDC 的 Session 306: Automating User Interface Testing with Instruments 【19】。 另外,这儿还有一篇很好的博客,详细的讲解了如何使用 UIAutomation 做 UI 自动化测试: http://blog.manbolo.com/2012/04/08/ios-automated-tests-with-uiautomation

Apple 通过 Instruments 为 UIAutomation 测试用例的命令行运行提供了支持,这样就为 UIAutomation 和 CI 服务器的集成提供了便利。开发者可以通过如下的步骤在命令行中运行 UIAutomation 测试脚本

  1. 指定目标设备,构建被测应用,该应用会被安装到指定的 DSTROOT 目录下
复制代码
xcodebuild
-project "/Users/twer/Documents/xcodeworkspace/AudioDemo/AudioDemo.xcodeproj"
-schemeAudioDemo
-sdk iphonesimulator6.1
-configuration Release SYMROOT="/Users/twer/Documents/xcodeworkspace/
AudioDemo/build" DSTROOT="/Users/twer/Documents/xcodeworkspace/AudioDemo/
build" TARGETED_DEVICE_FAMILY="1"
install
  1. 启动 Instruments,基于第一步生成的应用运行 UIAutomation 测试
复制代码
instruments
-t "/Applications/Xcode.app/Contents/Applications/Instruments.app/
Contents/PlugIns/AutomationInstrument.bundle/Contents/Resources/
Automation.tracetemplate" "/Users/twer/Documents/xcodeworkspace/AudioDemo
/build/Applications/TestExample.app"
-e UIASCRIPT <absolute_path_to_the_test_file>

为了更好的展示测试效果以及与 CI 服务器集成,活跃的社区开发者们还尝试把 UIAutomation 和 Jasmine 集成: https://github.com/shaune/jasmine-ios-acceptance-tests

UIAutomation 因其原生支持,并且通过和 Instruments 的绝佳配合,开发者可以非常方便的使用录制操作自动生成测试脚本,赢得了很多开发者的支持,但是因苹果公司的基因,其系统非常封闭,导致开发者难以扩展,于是活跃的社区开发者们开始制造自己的轮子,Fone Monkey 就是其中的一个优秀成果。

Fone Monkey

Fone Monkey 是由 Gorilla Logic 公司创建并维护的一个 iOS 自动化测试工具,其功能和 UIAutomation 差不多,但是由于其开源特性,极大的解放了活跃开发者的生产力,开发者可以很容易的根据自身需要扩展其功能。

Fone Monkey 的安装虽然简单,但是比 UIAutomation 的原生支持来说,也算是一大劣势了,具体的安装过程可以参考: http://www.gorillalogic.com/fonemonkey-ios/fonemonkey-setup-guide/add-fonemonkey-your-xcode-project

Fone Monkey 的使用方式主要就是录制 / 回放,也可以把录制好的测试用例保存为脚本以其他方式运行。安装好 Fone Monkey 启动测试以后,应用界面会有点变化:

开发者通过点击 Record 按钮录制操作,点击 Play 按钮播放之前录制的操作,点击 More 按钮可以添加一些针对元素的验证, 这样就形成了一个测试用例。

在 Fone Monkey 中录制的测试用例可以保存为 3 种格式,以支持多种运行方式:

  • scriptName.fm:用于支持在 Fone Monkey 的窗口中运行测试
  • scriptName.m:用于和 Xcode 的 OCUnit test 集成,可以以 OCUnit 的测试用例的形式运行 UI 测试,这就让 UI 具备了命令行运行和与 CI 集成的能力。
  • scriptName.js:UIAutomation 的格式,用于支持在 Instruments 中,以 UIAutomation 的形式运行测试。
2013-09-17 03:4010993

评论

发布
暂无评论
发现更多内容

腾讯云TDSQL-C云原生数据库技术

腾讯云数据库

数据库 tdsql

腾讯云TDSQL助力金融核心系统数字化转型

腾讯云数据库

数据库 tdsql

华为云正式推出区块链服务!区块链技术将在数字经济时代大放异彩

CECBC

使用Tapdata一步搞定关系型数据库到MongoDB的战略迁移

tapdata

双碳目标带来的机遇与挑战

石云升

新能源革命 碳中和 碳达峰 9月日更

北京建全球领先区块链算力平台,可满足未来各类场景需求

CECBC

谈谈汽车芯片安全(下篇)

SOA开发者

直击灵魂!美团大牛手撸并发原理笔记,由浅入深剖析JDK源码

Java 编程 架构 面试 程序人生

“智感超清”之HDR技术落地实践

百度开发者中心

最佳实践 音视频

八月热点抢先看:EasyDL图像分割数据自动贴合标注,标注效率提升30倍+

百度大脑

人工智能

千万级学生管理系统的考试试卷存储方案

Geek_db27b5

斯图飞腾Stratifyd亮相Smart Retail,AI赋能零售新增长

横空出世!复盘B站面试坑我最深的JDK源码剖析,全是干货!

Java 程序员 架构 架构师 计算机

金九银十已经过半还没拿到offer?阿里大牛熬夜整理的Java面试总结,网友已被震惊到说不出话!

Java 编程 面试 程序人生 金九银十

云计算科普:Pets(宠物)和Cattle(牲口)傻傻分不清楚?

刘华Kenneth

云计算 架构 云技术

TDSQL数据同步和备份

腾讯云数据库

数据库 tdsql

一张图读懂Z-ONE Digital Car

SOA开发者平台

冲破“薪资”瓶颈,某厂的玩转Java面试指南,他看完涨薪10k了!

Java 程序员 架构 编程语言

架构作业 - 模块四 存储架构

Leo Zhao

架构训练营

Redis可观测最佳实践,5大关键指标最全解析!

观测云

redis

谈谈汽车芯片信息安全(上篇)

SOA开发者

To B的软件产品死结怎么解?

刘华Kenneth

tob产品 客户服务

2021字节跳动面试总监首发1121道LeetCode算法刷题笔记(含答案)

Java 面试 程序人生 计算机

“碳中和”的未来蓝图中,区块链所占据的重要位置

CECBC

拥抱云原生,华为云GaussDB全新助力金融行业数字化转型

华为云数据库小助手

GaussDB GaussDB(for openGauss) 华为云数据库

第4章-《Linux一学就会》- vim编辑器和恢复ext4下误删文件-Xmanager工具

学神来啦

vim Linux 运维 VI

一张图读懂Z-ONE Studio Lite

SOA开发者

一张图读懂Z-ONE Digital Car

SOA开发者

智能网联汽车安全架构系列1:ECU安全机制介绍

SOA开发者

软件定义汽车技术体系研究

SOA开发者

浪潮云说丨浪潮云行·物联边缘云产品,让物联感知无微不至

云计算,

构建iOS持续集成平台(二)——测试框架_DevOps & 平台工程_刘先宁_InfoQ精选文章