1. 什么是Mock

当我们在做单元测试的过程中,为了保持测试又短又快和测试的隔离性,希望尽可能少地去实例化一些具体的组件。在现在面向对象的系统中,被测试的对象很可能会依赖于几个其他的对象,这时候我们就可以使用Mock去代替实例化这些对象。简单来说,Mock就是在测试中伪造的具有预定行为的具体对象的替身对象。因为被测试对象无法分辨出具体对象和替身对象的差别,所以可以用替身对象去代替具体对象执行测试。

2. 使用Mock的好处

构造一些使用具体对象难以构造或难以出现的对象。如我们朝服务器(第三方服务器)发送请求,也许100次中只返回一次Error,而当我们要测试返回Error情况下的系统的行为是否符合预期,使用具体对象完成比较困难,这时候就需要构造MockObject。

减少一些耗时的操作,例如我们需要测试访问数据库,而访问这个数据库开销巨大的时候,我们可以构造一个“虚拟”的数据库,让这个数据库返回我们期望的特定值即可。

甚至有时候因为需要内网或者屏蔽等原因,无法连接服务器的情况,也可以使用“虚拟”一个网络连接或服务器,让它返回我们期望的数据即可。

3. 测试框架简介

XCTest Or GHUnit

  XCTest GHUnit
简述 苹果官方提供的测试框架 相对热门的第三方测试框架
优点 与XCode深度集成,无需安装,而且可以享受苹果后续的维护 有自己的GUI界面,测试结果直观
缺点 测试结果难找且信息冗杂 集成度不如XCTest,安装麻烦,不能单独运行某个测试

XCTest和GHUnit都有各自的优缺点,相对来说GHUnit所提供的便利意义并不大,所以更多的开发者会选择XCTest。

以下是一些Github上的一些知名的开源库的测试框架选择:

Expect Or OCHamcrest

  Expecta OCHamcrest
简述 两者都是断言的扩展框架,都依赖于CocoaPods 起源于Java的Hamcrest,OCHamcrest是Hamcrest的一个Objective -C版本
优点 断言不必考虑数据类型,可读性强,使用方便 框架成熟,预定义的断言更加丰富,可自定义断言,可扩展性高
缺点 预定义断言不够多,可扩展性不高  

TDD Or BDD Or Not

TDD 的全称是Test Driven Development,也就是测试驱动开发。它与软件传统的先开发后验证的模式不同,是先验证后开发。举个例子来说,师傅砌砖,在TDD模式下会先拉线后砌砖,这样砌出来的砖都是整齐的。而一些新来的师傅可能会先砌砖,然后再拉线检查砖是否整齐,若砖不整齐,再继续做后续的工作。这样一听,感觉TDD是不是很厉害,但实现起来非常困难。

BDD的全称是Behavior Driven Development,也就是行为驱动开发,通过测试来推动整个开发的进行。BDD的理念是描述行为,所以感觉不是在写代码,而是在讲故事。因此BDD的测试开发语言都十分接近自然语言,可读性非常强,让有眼前一亮。现有的BDD框架大多由三部分构成(Given....When....Then....)组成,下面是一段Objective-C语言的BDD框架Kiwi的一段测试代码:

这个测试用例就是在说Give a Team, when newly created, it should have a name, and should have 11 players. 翻译成中文就是一个足球队成立的时候,它应该有一个队名和11位球员。基本不用注释就能很容易的读懂这个测试做了什么。BDD框架的语法差别不大,十分易读。目前iOS相关的BDD开源热门框架有:

框架名称 测试语言 GitHub Stars 备注
Kiwi Objective-C      3223 Kiwi自带Mock功能,是基于OCMock实现的,所以不能和OCMock共用
Specta Objective-C      1692 Kiwi可以看做是带有Mock和Expecta功能的Specta
Quick Swift(Objective-C)      4698  
Sleipnir Swift       795  
Cedar Objective-C      1079  

对于BDD框架的选择,使用或不使用更多开发的项目。BDD测试代码可读性高,不过相对于XCTest和OCMock的组合,具有一定的学习成本且文档不如后者丰富,在封装过程中也失去了一定的灵活性。

目前使用过的BDD框架Kiwi和Specta都不支持单独运行某个测试样例,只能使用Command+U一次运行所有测试样例,当测试样例逐渐增多的时候就不得不运行一些不想要做的测试。

4. OCMock简介

如果你已经理解了什么是Mock,那么OCMock就是Objective-C语言下的一个Mock框架。目前OCMock的版本是OCMock3,其API不太多,使用起来方便,这里简单介绍一些:

Mock的模式:

模式 描述 API
Strict Mode       严格类型的Mock,当Mock对象调用了没有被Stub的方法会抛出异
常。即严格意义上的完全Mock。
id strictMock = OCMStrictClassMock([NSUserDefaults class]);
Nice Mode      友好类型的Mock,当Mock对象调用了没有被Stub的方法不会抛出
异常。目前是默认的Mock类型。

 id niceMock = OCMClassMock([NSUserDefaults class]);
Partial Mode        部分类型的Mock,当Mock对象调用了没有被Stub的方法会直接执
行具体对象的方法。

NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];

id partialMock = OCMPartialMock(defs);

Expect-Run-Verify 和  Verify after running

大多数的Mock框架都遵循了Expect-Run-Verify的原则,老版本的OCMock就是其中之一,这种方法出现了一些弊端。OCMock3支持了一种新的验证方法Verify After Running,我们不用在运行结束就立即去验证结果。只要在运行之后,只要在想要验证的时候调用OCMVerify即可。

NSInvocation

在OCMock中如果使用了Block绑定参数,那么就需要和NSInvocation打交道,在Objective-C中,NSInvocation有两个默认的参数(0: self , 1:_cmd),在绑定参数的时候要从2开始算。如:

- (void)downloadWeatherDataForZip:(NSString *)zip callback:(void (^)(NSDictionary *response))callback;

如果要动态绑定Callback,那么它对应的序号应该是3(0: self, 1: _cmd, 2: zip, 3: callback)。

通过[invoke getArgument:&storageVariableName atIndex:3];即可。

5. UI Tests相关

待补

6. Unit Tests相关

处理私有方法和属性

按照测试的原理,我们不应该去测试私有的方法。但在我们测试的时候可能会调用一个私有方法或者私有属性,如果不将其改为公有是无法去验证这些行为的。这种情况,我们可以在测试文件的开头用一个名为UnitTest的Category来暴露私有方法和属性。如:

7. 相关页面

英文原文:XCTest实战经验

中文翻译:XCTest实战经验

iOS开发中的测试框架

单元测试框架选择

OCMock官网

OCMock的常见使用方式

wwdc 2015 session UI Testing PDF

UITests Tutorial

5.iOS测试总结的更多相关文章

  1. 互联网App应用程序测试流程及测试总结

    互联网App应用程序测试流程及测试总结 1. APP测试基本流程 1.1流程图 仍然为测试环境 Pass 1.2测试周期 测试周期可按项目的开发周期来确定测试时间,一般测试时间为两三周(即15个工作日 ...

  2. IPv6升级测试指南(Android/iOS/Mac)

    目录 我们升级到IPv6的原因 测试的时候的注意要点 Android/IOS/MAC测试总结 Android测试IPv6的方法 IOS端测试IPv6的方法 MAC浏览器端测试IPv6的方法 升级IPV ...

  3. iOS 测试在应用发布前后的痛点探索以及解决方案

    作者-芈 峮 前言 iOS 开发从 2010 年开始在国内不断地升温,开发和测试相关的问题不绝于耳.iOS 测试主要涉及哪些内容?又有哪些挑战呢?带着疑问我们开始第一个大问题的讨论. iOS 测试的范 ...

  4. iOS可视化动态绘制连通图

    上篇博客<iOS可视化动态绘制八种排序过程>可视化了一下一些排序的过程,本篇博客就来聊聊图的东西.在之前的博客中详细的讲过图的相关内容,比如<图的物理存储结构与深搜.广搜>.当 ...

  5. 【疯狂造轮子-iOS】JSON转Model系列之二

    [疯狂造轮子-iOS]JSON转Model系列之二 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇<[疯狂造轮子-iOS]JSON转Model系列之一> ...

  6. 【疯狂造轮子-iOS】JSON转Model系列之一

    [疯狂造轮子-iOS]JSON转Model系列之一 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 之前一直看别人的源码,虽然对自己提升比较大,但毕竟不是自己写的,很容易遗 ...

  7. iOS总结_UI层自我复习总结

    UI层复习笔记 在main文件中,UIApplicationMain函数一共做了三件事 根据第三个参数创建了一个应用程序对象 默认写nil,即创建的是UIApplication类型的对象,此对象看成是 ...

  8. iOS代码规范(OC和Swift)

    下面说下iOS的代码规范问题,如果大家觉得还不错,可以直接用到项目中,有不同意见 可以在下面讨论下. 相信很多人工作中最烦的就是代码不规范,命名不规范,曾经见过一个VC里有3个按钮被命名为button ...

  9. JS调用Android、Ios原生控件

    在上一篇博客中已经和大家聊了,关于JS与Android.Ios原生控件之间相互通信的详细代码实现,今天我们一起聊一下JS调用Android.Ios通信的相同点和不同点,以便帮助我们在进行混合式开发时, ...

随机推荐

  1. ie67 display:inline-block 失效解决方法

    先将其转化为块状,在转化为inline,*号为css hcak,代表针对IE67 display: inline-block; *display: block; *display: inline;

  2. java 获取路径

    1.利用System.getProperty()函数获取当前路径:System.out.println(System.getProperty("user.dir"));//user ...

  3. LIS n^2&nlogn模板

    LIS nlogn模板 http://acm.hdu.edu.cn/showproblem.php?pid=1950 #include <iostream> #include <st ...

  4. iOS多线程全套:线程生命周期,多线程的四种解决方案,线程安全问题,GCD的使用,NSOperation的使用

    目的 本文主要是分享iOS多线程的相关内容,为了更系统的讲解,将分为以下7个方面来展开描述. 多线程的基本概念 线程的状态与生命周期 多线程的四种解决方案:pthread,NSThread,GCD,N ...

  5. HTTPS站点搭建教程:Win7/Windows Server 2008R2

    本文将由笔者为各位读者介绍在win7/windows server 2008R2环境下使用SSL加密协议建立WWW站点的全过程:https SSL证书安装的搭建以及本地测试环境. 要想成功架设SSL安 ...

  6. 【HDU 2089】 不要62

    [题目链接] 点击打开链接 [算法] 数位DP 和上一题 : HDU3555很像 [代码] #include<bits/stdc++.h> using namespace std; #de ...

  7. unity anim(转)

    Unity4的Mecanim动画很早以前就有体验过,迟迟没有加到项目中有两个原因,今天写这篇博客来记录我在做的过程中遇到的一些问题. 1.以前的代码代码量比较多,修改起来动的地方太多了. 2.使用Me ...

  8. Linux和windows下执行sql脚本文件

    利用 sqlplus 登录数据库之后 键入: @/全路径/文件名      即可执行*.sql 文件            例 假设有一个 test.sql 文件 所在路径是/home/oracle/ ...

  9. 【旧文章搬运】Idle进程相关的一些东西

    原文发表于百度空间,2009-05-13========================================================================== Idle进 ...

  10. Java中的Cloneable接口与深拷贝、浅拷贝

    Cloneable接口是一个标记接口,也就是没有任何内容,定义如下: 这里分析一下这个接口的用法,clone方法是在Object种定义的,而且是protected型的,只有实现了这个接口,才可以在该类 ...