iOS输入法—基于XCTest框架的异步测试
苹果今年在Xcode 6中添加了XCTest框架此前漏掉的几项功能,这当中的异步测试功能大大方便了我们的测试工作。
如果我们的测试项目要执行一个异步任务,它可能会跑在其它的线程里,也可能会跑在主线程的RunLoop里,在这种时候我们应该如何去进行测试呢?来看一个非常简单的例子!
现在有一个web请求的功能需要测试。我们会开始web请求然后进入阻塞,接下来在程序完成的代码块中做一个测试断言。然而,鉴于没有web请求的情况下更谈不上响应,为了调用程序完成部分的代码我们就需要在断言之前确保被测试的方法已经在执行。
在通常情况下我们不会真的在测试时去做web响应,而是用一些工具来中断响应。不过在下面的例子里面我们需要更改一下规则——真正的完成一个web响应来进行测试。
我们使用了一个URL和一个程序完成块来模拟这个类的一个方法,它会下载URL所指的页面并调用这个程序块,如果成功会得到一个包含web页面的字符串,而发生错误的时候则是一个空字符串。
- (void)testCodeYouShouldNeverWrite { __block NSString *pageContents = nil; [self.pageLoader requestUrl:@" http://123.sogou.com " completionHandler:^(NSString *page) { NSLog(@"The web page is %ld bytes long.", page.length); // Test method ends before this test assertion is called XCTAssert(pageContents.length > 0); pageContents = page; }]; // Nothing prevents the test method from returning before // completionHandler is called. } |
很显然,这种测试方法是有问题的!
在Xcode 6之前的版本里面并没有内置XCTest,想使用Xcode测试的只能是在主线程的RunLoop里面使用一个while循环,然后一直等待响应或者直到timeout,下面就是这种旧方法的代码:
- (void)testAsyncTheOldWay { NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:5.0]; __block BOOL responseHasArrived = NO; [self.pageLoader requestUrl:@" http://123.sogou.com" completionHandler:^(NSString *page) { NSLog(@"The web page is %ld bytes long.", page.length); responseHasArrived = YES; XCTAssert(page.length > 0); }]; while (responseHasArrived == NO && ([timeoutDate timeIntervalSinceNow] > 0)) { CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.01, YES); } if (responseHasArrived == NO) { XCTFail(@"Test timed out"); } } |
这个while循环在主线程里面每隔10毫秒会跑一次,直到有响应或者5秒之后超出响应时间限制才会跳出。这个方法十分有效而且看上去也不糟,但这并不意味着开发的终结——这个方法还是不够好。接下来说一个更加优化的办法。
在Xcode 6里,苹果以XCTestExpection类的方式向XCTest框架里添加了测试期望(test expection)。当我们实例化一个测试期望(XCTestExpectation)的时候,测试框架就会预计它在之后的某一时刻被实现。最终的程序完成代码块中的测试代码会调用XCTestExpection类中的fulfill方法来实现期望。
这一方法替代了我们之前例子里面使用responseHasArrived作为Flag的方式,这时我们让测试框架等待(有时限)测试期望通过XCTestCase的waitForExpectationsWithTimeout:handler:方法实现。如果完成处理的代码在指定时限里执行并调用了fulfill方法,那么就说明所有的测试期望在此期间都已经被实现。否则,这个测试就悲剧了,它会默默的存在程序中而不会被实现哪怕一次……
当然,失败结果并不意味着失败的测试,只有不明就里的测试结果才算失败的测试。
下面是使用XCTestExpection的示例:
(void)testWebPageDownload { XCTestExpectation *expectation = [self expectationWithDescription:@"High Expectations"]; [self.pageLoader requestUrl:@"http://123.sogou.com” completionHandler:^(NSString *page) { NSLog(@"The web page is %ld bytes long.", page.length); XCTAssert(page.length > 0); [expectation fulfill]; }]; [self waitForExpectationsWithTimeout:5.0 handler:^(NSError *error) { if (error) { NSLog(@"Timeout Error: %@", error); } }]; } |
在最后的代码段里面使用[expectation fulfill]来告知此次测试所期望的部分已经确切实现过了。
然后用waitForExpectationsWithTimeout:handler方法等待响应,这段会在接受响应之后执行……或者超时之后也会执行。
原文链接
如需转载该篇文章,请注明来自“搜狗测试”
iOS输入法—基于XCTest框架的异步测试相关推荐
- 基于PACT框架的契约测试在微服务架构中的应用
背景信息 在软件工程领域,我们经常面临变化."概念的到来,微服务 "是那些最近发生的事件,它不仅改变了软件的架构,而且球队的组织方式以及它们如何协同工作之一. 以下是由M. Fow ...
- 自动化测试(二)01-前端测试分为单元测试、集成测试和E2E测试 测试工具对比-适合TDD或 BDD、断言、异步测试 测试工具的类型
自动化测试(二)01-前端测试分为单元测试.集成测试和E2E测试 & 测试工具对比-适合TDD或 BDD.断言.异步测试 & 测试工具的类型 前端自动化测试 测试是一个庞大的主题,包括 ...
- iOS开发--Kiwi使用进阶 Mock, Stub, 参数捕获和异步测试
Kiwi 是 iOS 的一个行为驱动开发 (Behavior Driven Development, BDD) 的测试框架,我们在上一篇入门介绍中简单了解了一些 iOS 中测试的概念以及 Kiwi 的 ...
- 构建iOS持续集成平台(二)——测试框架
[原文地址:http://www.infoq.com/cn/articles/build-ios-continuous-integration-platform-part2#0-tsina-1-332 ...
- IOS基础基于pod上手体验FMDB框架
IOS基础基于pod上手体验FMDB框架 // // ViewController.m // FMDBSingleOC // // Created by 鲁军 on 2021/3/17. //#imp ...
- android输入法框架分析,Android与iOS输入法开发框架比较谈
对于任何一个使用手机的人,有一样工具是不可能缺少的,它既不是微信之类的社交工具,也不是支付宝之类的金融工具(事实上这两个都越界了),而是输入法这样的输入工具.更重要的是,输入法还是一种特权工具,因为它 ...
- 魔坊APP项目-18-种植园,基于支付宝提供的沙箱测试环境开发支付接口、服务端, 处理支付结果的同步通知和异步通知、修复页面底部菜单无法被点击的BUG
种植园 一.基于支付宝提供的沙箱测试环境开发支付接口 沙箱环境: https://openhome.alipay.com/platform/appDaily.htm?tab=info 开发文档: ht ...
- 基于SSM框架社交媒体实现
本文由本人的本科毕业论文修改而来,并不是论文的完整篇幅,部分已进行修改或删除.注意,在参考时还请注意查重等其他因素,由此所产生的相关问题均与本人无关,概不负责. 目录 摘要 Abstract 第一章 ...
- Kiwi 使用进阶 Mock, Stub, 参数捕获和异步测试
Kiwi 是 iOS 的一个行为驱动开发 (Behavior Driven Development, BDD) 的测试框架,我们在上一篇入门介绍中简单了解了一些 iOS 中测试的概念以及 Kiwi 的 ...
最新文章
- android jar 包 意见反馈功能,android重点jar包详解.docx
- 设计资源类的网站有哪些?
- mysql用命令行创建表_mysql命令行创建表
- [C++] C/C++结构体的区别
- Rust : 闭包、move、复制与移动语义
- 【图文详解】Python(3.9.6)安装教程 + pip安装教程
- 台式计算机硬盘的安装位置,台式电脑分别如何安装SSD(固态硬盘)详细图文教程...
- 颜色代码查询,在线颜色选择器,RGB颜色对照表
- 语言学句法分析树形图怎么画_科学网—《泥沙龙笔记:漫谈自动句法分析和树形图表达》 - 李维的博文...
- allegro 导 bom
- Novell NetWare 及其协议
- 《WebRTC 1.0: Real-Time Communication Between Browsers》学习
- 在微软官方网站”满速”下载Windows10最新系统镜像方法。
- 中国拳手徐灿将战世界拳王:有信心把金腰带带回祖国
- org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont.addNewFamily()
- arduino智能浇花系统_基于Arduino的远程自动浇花系统设计
- TI am335x U-boot
- oracle导入dmp秒退,Oracle导入dmp遇到问题解决
- 你想去看电影吗?电影院的未来可能会很像苹果商店
- 首届实时渲染3D动画创作大赛结果公布,看大奖英伟达A6000花落谁家