iOS单元测试框架选型

1.前言

1.1测试的目的

  • 在开发前期检验了代码逻辑的正确性,开发后期,无论是修改代码内部抑或重构,测试的结果为这一切提供了可量化的保障。
  • 可以便捷的对某个具体方法进行功能测试。
  • 对方法性能测试,如耗时测试

1.2适合测试场景

  • 模块比较稳定的回归测试
  • 极限操作的测试
  • 长时间监控类测试
  • 性能测试

2.方案选择

2.1 单元测试框架

常见的单元测试框架有XCTest 、GHUnit 、Kiwi

XCTest:与Xcode深度集成。而且可以享受Apple后续对XCTest升级的福利,配合OCMock使用是知名第三库常使用的方案

GHUnit:GitHub 上著名的开源测试框架,可视化、开源、扩展等功能,让其相比 XCTest 更加强大(现在的 XCTest 也很完善了, GHUnit 比较老,现在已经停止维护,不建议使用)

Kiwi:BDD框架,行为驱动框架,可读性较高,但重量级的,集 OCMock、Specta、Expecta 所拥有的功能与一身,最小测试单位为一个测试用例类,灵活性较低。

知名开源库的单元测试框架:

AFNetworking:XCTest

AsyncDisplayKit:XCTest+OCMock

FMDB:XCTest

FBKVOController:XCTest + OCMockito + OCHamcrest

个人推荐使用Xcode自带的XCTest+OCMock/OCMockito

2.2 UI测试框架

Appium:通过驱动UI Automation控制手机UI操作。但是,由于Xcode 8

以后UI Automation没有了,因此导致无法直接使用Appium。

KIF:KIF一个建立在XCTest的UI测试框架,能和应用的代码工程完美结合。通过accessibility来定位具体的控件,再利用私有的API来操作UI。很多大公司如Google都在使用这个测试框架。

个人推荐UI测试框架使用KIF

3.现有工程添加单元测试

3.1 创建单元测试Target

File->New->Target,然后选中“iOS”在搜索框里输入 test ,就能看到 “iOS UITesting Bundle”和 “iOS Unit Testing Bundle”两个图标了

image.jpeg

选中后点击“Next”按钮后,分别创建如下两个taget:

KMeetingUnitTestDemoTests(单元测试,测试每一个类能够正常工作)和KMeetingUnitTestDemoUITests(UI测试,也叫做集成测试,从业务层的角度保证各个业务可以正常工作)

image.jpeg

3.2 单元测试类介绍

image.jpeg
  • setUp 用于做一些初始化代码
  • tearDown用于对象的销毁
  • 所有测试类都必须继承XCTestCase
  • 测试方法必须以testXXX开头,Xcode会自动识别出所有的测试方法
  • 在一个类中测试方法的调用顺序是按照方法的顺序来调用的

调用

  • 执行所有测试方法:command + u
  • 只执行某个测试方法:点击方法前的菱形(目前是对号/错号)
  • 执行某个类的所有测试方法:点击类前的菱形(目前是对号/错号)

3.3 简单使用

对ViewController添加如下方法,然后Common+U进行测试:

  • (NSInteger)addA:(NSInteger)a andB:(NSInteger)b;
image.jpeg

注:XCTAssertTrue(expression, format...)当expression求值为TRUE时通过,如果不通过则显示format。

3.4 方法性能测试

对比for in 与 enumerate遍历耗时,初始化数组

image.jpeg

设置baseline0.03s

image.jpeg

运行结果


image.jpeg

3.5 OCMock的使用

当我们写单元测试的时候,不可避免的要去尽可能少的实例化一些具体的组件来保持测试既短又快。测试的方法引用很多外部依赖的对象时,用mock来替代实例化具体的依赖class可以保持单元的隔离。

参考:https://github.com/erikdoe/ocmock

PS:常用断言语句用法如下:

  • XCTFail(format…) 生成一个失败的测试;
  • XCTAssertNil(a1, format...)为空判断,a1为空时通过,反之不通过;
  • XCTAssertNotNil(a1, format…)不为空判断,a1不为空时通过,反之不通过;
  • XCTAssert(expression, format...)当expression求值为TRUE时通过;
  • XCTAssertTrue(expression, format...)当expression求值为TRUE时通过;
  • XCTAssertFalse(expression, format...)当expression求值为False时通过;
  • XCTAssertEqualObjects(a1, a2, format...)判断相等,[a1 isEqual:a2]值为TRUE时通过,其中一个不为空时,不通过;
  • XCTAssertNotEqualObjects(a1, a2, format...)判断不等,[a1 isEqual:a2]值为False时通过;
  • XCTAssertEqual(a1, a2, format...)判断相等(当a1和a2是 C语言标量、结构体或联合体时使用, 判断的是变量的地址,如果地址相同则返回TRUE,否则返回NO);
  • XCTAssertNotEqual(a1, a2, format...)判断不等(当a1和a2是 C语言标量、结构体或联合体时使用);
  • XCTAssertThrows(expression, format...)异常测试,当expression发生异常时通过;反之不通过;
  • XCTAssertThrowsSpecific(expression, specificException, format...) 异常测试,当expression发生specificException异常时通过;反之发生其他异常或不发生异常均不通过;
  • XCTAssertThrowsSpecificNamed(expression, specificException, exception_name, format...)异常测试,当expression发生具体异常、具体异常名称的异常时通过测试,反之不通过;
  • XCTAssertNoThrow(expression, format…)异常测试,当expression没有发生异常时通过测试;
  • XCTAssertNoThrowSpecific(expression, specificException, format...)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过;
  • XCTAssertNoThrowSpecificNamed(expression, specificException, exception_name, format...)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过

3.6 查看代码覆盖率

打开Edit Scheme,勾选Gather coverage for

image.jpeg

运行用例,查看结果

image.jpeg

点击展开相应的类,可查阅该类未测试到的方法。

4.UI集成测试

4.1 KIF框架介绍

  • KIF的本质还是XCTest,它继承了XCTest在其基础上增加了UI测试的能力,提供了非常丰富的UI测试的接口。

4.2 KIF的使用

  • 首先,基于KIFTestCase新建测试类,对一个简单的登录界面测试。虽然它生成的内容与XCTest相似,但事实上,由于KIF做了封装,原来用来做初始化的setUp()及tearDown()都不再需要了,所以KIF封装了几个更好用的接口,下面将进行介绍。

1.-(void)beforeAll。在本类中第一个test case执行前执行一次,用于执行当前类中各个测试函数的公共操作。(因为不能保证这个方法与test case是同一个类实例,所以不能用来设置实例变量的值,但是可以设置静态变量)

2.-(void)beforeEach。在每个test case执行前执行一次,用于执行各个函数需要的测试环境。因为这个方法与test case是同一个类实例,所以可以用来设置实例变量。

3.-(void)afterEach。在每个test case执行后执行一次,用来将App恢复至test case之前的状态,可以包含一些条件判断逻辑,从失败的test case中恢复,以确保不影响之后的测试。

4.-(void)afterAll。执行完测试类的最后一个test case后执行一次,一般用于将App恢复至测试的初始状态。

  • 获取对应控件,并做一些UI操作

1. 根据Accessibility获取输入框控件

 //根据Accessibility获取控件
  UITextField *nameTF = (UITextField*)[tester waitForViewWithAccessibilityLabel:@"nameTF"];
  UITextField *pwdTF = (UITextField*)[tester waitForViewWithAccessibilityLabel:@"pwdTF"];

注:需要在原始的类中设置Accessibility,如 [self.nameTF setAccessibilityLabel:@"nameTF"];

2.向控件输入内容

//输入内容
 [tester clearTextFromAndThenEnterText:@"ABC" intoViewWithAccessibilityLabel:@"nameTF"];
 [tester clearTextFromAndThenEnterText:@"123456" intoViewWithAccessibilityLabel:@"pwdTF"]

3.点击按钮

//点击控件
 [tester tapViewWithAccessibilityLabel:@"loginBtn"];

4.等待特定控件出现

//10s后未出现预设控件,测试失败
 [tester waitForViewWithAccessibilityLabel:@"loginBtn"];

更多UI操作,参考https://github.com/kif-framework/KIF

5.其他辅助框架

Expecta Or OCHamcrest

ExpectaOCHamcrest这两个都是断言的扩展框架,Expecta最近很少更新,相对老旧,OCHamcrest持续更新,扩展性更好,推荐使用OCHamcrest。

OHHTTPStubs

在需要伪造网络请求返回的数据,模拟网络请求时的慢网环境情况使用

https://github.com/AliSoftware/OHHTTPStubs

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容

  • 一、简介[https://www.jianshu.com/writer#%E4%B8%80%E7%AE%80%E4...
    豆宝的老公阅读 1,095评论 0 1
  • 在计算机编程中,单元测试(英语:Unit Testing)又称为模块测试, 是针对程序模块的最小单位来进行正确性检...
    iOS暮光阅读 348评论 0 0
  • 前言: 对于单元测试来说,我想大部分同行,在项目中,很少会用到,也有一大部分,知道单元测试这个东西,但是确切的说没...
    麦穗0615阅读 3,217评论 4 44
  • 单元测试不是一个小工程,需要多用些时间才能做好,不要希望通过这个文章就能掌握单元测试,这只是一个入门,需要自己动手...
    勇不言弃92阅读 7,800评论 9 60
  • 0.绪论[http://wiki.baidu.com/pages/viewpage.action?pageId=1...
    Ferrari1001阅读 591评论 0 2