基于测试驱动的iOS开发

第一次接触基于测试驱动的iOS开发应该是2013年11月那会了。时间过得真快,现在都快三年了。那会Xcode版本还是4.6,单元测试用的OCUnit框架,自从XCode 5之后就变成了XCTest了,Xocde 7 之后又有了UI Testing的测试了,苹果的测试真是玩的越来越666了。主要的iOS单元测试框架有XCTest,GHUnit,OCMock等。果然,大学里学的软件测试专业课还是很有用处的,记得当时老师讲的最深刻的还是基于Socket的网络编程,一大堆基于测试用例的条件编写的白盒测试。黑盒测试,系统测试,回归测试等等。。。

UI Tests是一个自动测试UI与交互的Testing组件。它可以通过编写代码、或是记录开发者的操作过程并代码化,来实现自动点击某个按钮、视图,或者自动输入文字校验等功能。

在实际的开发过程中,随着项目越做越大,功能越来越多,仅仅靠人工操作的方式来覆盖所有测试用例是非常困难的,尤其是加入新功能以后,旧功能也要重新测试一遍,这导致了测试需要花非常多的时间来进行回归测试,这时就产生了大量重复的工作,也会导致上线时间的耽搁。而这些重复的工作有些是可以自动完成的,这时候UI Tests就可以帮助解决这个问题了。

而自动化的测试框架,在Android平台有较为成熟的Monkey工具,iOS平台就显得有点鸡肋了。自打Xcode7加入了UI Testing的框架,iOS的自动化测试才有了一片光明。Instrument工具有一项UIAutomation,通过结合Javascript脚本和Accessibility来推进自动化的步伐。自动生成测试时,先选择测试文件后,在调试区域点击录制按钮,就是一个小红圆点,这时候开始进行操作,它会记录你的操作步骤,并生成测试代码。这时候可以分析测试代码的语法,以便你自己手动修改或者手写测试代码

单元测试的魅力

1.她能让你更自信。帮助你编写高质量代码、减少bug。
如果大家分析一下我们bug原因的构成,我想有会有一部分bug的原因是开发人员在编写工作代码的时候没有考虑到某些case或者边际条件。造成这种问题的原因很多,其中很重要的一个原因是我们对工作代码所要完成的功能思考不足,而编写单元测试,特别是先写单元测试再写工作代码就可以帮助开发人员思考编写的代码到底要实现哪些功能。例如实现一个简单的用户注册功能的业务类方法,用单元测试再写工作代码的方式来工作的话开发人员就会先考虑各种场景相关,例如正常注册、用户名重复、没有满足必要的填写内容......等等,之后就会编写相关的测试用例。编写单元测试代码的过程就是促使开发人员思考工作代码实现内容和逻辑的过程,之后实现工作代码的时候,开发人员思路会更清晰,实现代码的质量也会有相应的提升。

2.她能提提升你的战斗力。帮助你提升代码的反馈速度,减少重复工作,提高开发效率。
开发人员实现某个功能或者修补了某个bug,如果有相应的单元测试支持的话,开发人员可以马上通过运行单元测试来验证之前完成的代码是否正确,而不需要反复通过编译运行simulator、等待应用启动、通过输入数据等繁琐的步骤来验证所完成的功能。用单元测试代码来验证代码和通过发布应用以人工的方式来验证代码这两者的效率差很多,所以单元测试其实还能节约人力成本。

3.她的存在让你轻松愉快。保证你最后的代码修改不会破坏之前代码的功能。
项目越做越大,代码越来越多,特别涉及到一些公用接口之类的代码或是底层的基础库,谁也不敢保证这次修改的代码不会破坏之前的功能,所以与此相关的需求会被搁置或推迟,由于不敢改进代码,代码也变得越来越难以维护,质量也越来越差。而单元测试就是解决这种问题的很好方法(不敢说最好的)。由于代码的历史功能都有相应的单元测试保证,修改了某些代码以后,通过运行相关的单元测试就可以验证出新调整的功能是否有影响到之前的功能。当然要实现到这种程度需要很大的付出,不但要能够达到比较高的测试覆盖率,而且单元测试代码的编写质量也要有保证。

4.她能为你排忧解难,永远做你的依靠。让你的代码维护更容易。
由于给代码写很多单元测试,相当于给代码加上了规格说明书,开发人员通过读单元测试代码也能够帮助开发人员理解现有代码。比如开源项目(如AFNetworking, FMDB,喵神的VVDoucment等)都有相当量的单元测试代码,通过读这些测试代码会有助于理解生产源代码。

5.她甘心做你坚强的后盾,在你卖命打拼时无后顾之忧。她有助于改进代码质量和设计。
除了那些大拿们编写的代码,我相信很多易于维护、设计良好的代码都是通过不断的重构才得到的。虽然说单元测试本身不能直接改进生产代码的质量,但它为生产代码提供了“安全网”,让开发人员可以勇敢地改进代码,从而让代码的clean和beautiful不再是梦想。

说了那么多,其实就是想表明基于测试驱动的开发,对你来说就达到了事半功倍的目的。

具体例子可以看看官网的Demo或者Google下了。https://developer.apple.com/library/content/samplecode/UnitTests/Introduction/Intro.html

Test 断言

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语言标量、结构体或联合体时使用,实际测试发现NSString也可以);

XCTAssertNotEqual(a1, a2, format...)判断不等(当a1和a2是 C语言标量、结构体或联合体时使用);

XCTAssertEqualWithAccuracy(a1, a2, accuracy, format...)判断相等,(double或float类型)提供一个误差范围,当在误差范围(+/-accuracy)以内相等时通过测试;

XCTAssertNotEqualWithAccuracy(a1, a2, accuracy, format...) 判断不等,(double或float类型)提供一个误差范围,当在误差范围以内不等时通过测试;

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没有发生具体异常、具体异常名称的异常时通过测试,反之不通过。

特别注意下XCTAssertEqualObjects和XCTAssertEqual。
XCTAssertEqualObjects(a1, a2, format...)的判断条件是[a1 isEqual:a2]是否返回一个YES。XCTAssertEqual(a1, a2, format...)的判断条件是a1 == a2是否返回一个YES。对于后者,如果a1和a2都是基本数据类型变量,那么只有a1 == a2才会返回YES。

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

推荐阅读更多精彩内容