第1章 软件测试与iOS测试
iOS平台的一些特性:
硬件特性
只有一个程序正在运行
有限内存和CPU
多样化不稳定的网络环境
多样化且不同尺寸的屏幕
用户使用特性
短时间内相应
多种输入方式:摇晃、使用地理位置等
第2章 iOS测试环境准备(略)
第3章 iOS单元测试
3.1工具
3.1.1 OCUnit (XCTest)
该工具现已被 XCTest 取代,但大致使用习惯和使用方法的变化不大。XCTest是Xcode自带的测试工具集,他有下面几个特性:
- 命名方式以 test 开头,如
testXXXX
- 测试类继承 XCTestCase ,只有继承它或其子类,才能去发现和执行测试方法
- 测试一定要有结果预期,表达预期结果使用断言
- 当 XCTest 执行一个测试方法时,会按顺序执行方法中每一行语句。在执行过程中,方法抛出了非预期的异常,会被立即停止,并计为失败。反之,全部执行完,就是测试成功了
- 一个测试用例中可以有多个测试方法,在每个测试方法执行前和执行后,会调用 setUp 和 tearDown 方法
3.1.2 GHUnit
GHUnit 是一个第三方的测试框架,它是一个开源项目,在 Github 上有1000+的 star,现在看来,已经不再加新特性,但是依然在维护中。在 Xcode 4 之前,OCUnit 有很多限制,所以涌现出来很多的三方测试框架,GHUnit 是其中一个。GHUnit 是以一个应用程序安装到手机里运行的,有测试相关的图形界面,和之前的 OCUnit 完全不同。在其主页上,我还看到它能够测试 UI 组件,比对视图的前后变化等 UI 方面的测试内容。
3.1.3 GTM (略)
3.2 单元测试实践
前面介绍了3种测试工具,作者选定的是 OCUnit 作为全书的实践测试工具。
被测试系统 SUT (System Under Test)
SUT 的形态分三种:
- 有明确返回值。可以直接验证返回值是否符合预期。
- 没有返回值。需要验证对象内部的一些属性和状态,这种方法称为状态验证法。经典实用场景:set 方法
- SUT 依赖于外部的一个类或方法,他会调用外部的一个方法,被依赖的外部方法可能有返回值也可能没有,这种叫行为验证法。这时需要验证的是是否发起了这个行为
3.2.1 实践项目介绍
这个项目是一个简单的计数器工具,点+1按钮数值加1,点-1按钮,数值减1。自己实现了书中 Demo: 计数器Demo,使用 XCTest 实现,可以在 Xcode 8 下直接运行。这个项目采用了 MVC 架构,作者构建了一个典型的 MVC 的通讯场景:View 通过 Target-Action 方式通知 Controller ,Controller 调用 Model 处理业务逻辑,Model 处理完通过 Notification 传递消息给 Controller,Controller 更新 View。作者在下面三个小结中,分别阐述了如何对 Model View&ViewController 做单元测试。
使用了两个三方框架
- OCHamcrest 断言功能更强大,可读性更好
- OCMockito Mock框架,可以 Mock 具体类,并指定该类的具体方法的返回值。
3.2.2 Model的单元测试
Model 待测试方法:
@property (nonatomic) NSUInteger count;
- (id)initWithUserDefault:(NSUserDefaults *)defaults;
- (void)increment;
- (void)decrement;
- (NSUInteger)getCountInDefaults;
测试代码见 Demo。主要使用下面3中测试方法:
- 注入依赖,通过 Mock 方法强制依赖返回结果(这里 Mock 了 NSUserDefaults),从而验证方法的返回值是否正确
- 注入依赖,通过该 Mock 方法验证某一个方法是否是以我们希望的方法调用了 (testIncrementShouldInvokeSetObject 中使用了 verify 宏来判定是否调用了某个具体方法)
- 被测试方法会发送 Notification,测试方法必须添加 Notification 的接收器来进行测试
3.3.3 Controller和View的单元测试
先看两者的交互:View 响应用户的操作后,调用 Controller 的方法 。Controller 处理完后会更新 View。其中 View 向 Controller 操作部分可以细分为下面三个步骤:
- 需要确认相关的 View 是否存在并且正确显示
- 需要确认相关的 View 是否绑定了正确的事件和方法
- 需要确认 Controller 发送消息的方法是否正确
而更新 View 的验证就相对简单,只要判断内容或者状态是否符合预期。属于上面 SUT 的状态验证法。
实际使用中,如果对 ViewController 进行测试,需要 Controller 暴露信息较多,否则在测试方法中,很难做到解耦,比较鸡肋。
3.4 单元测试的拓展工具
OCHamcrest IOS单元测试的扩展工具OCHamcrest
OCMockito IOS单元测试工具之OCMockito
关于单元测试的详细内容,可以参考《测试驱动的iOS开发》一书,能有更细致了解。