我们之前谈到过要让开发人员认识到测试的重要性并了解测试、如何写出简洁的单元测试,单元测试下的开发模式,今天我们来讲讲单元测试开发模式下的测试框架。
Kiwi
BDD 框架里的 Kiwi 可圈可点。使用 CocoaPods 引入 pod ‘Kiwi’,看下面的例子。
被测类(Planck 项目是一个基于 WebView 的 SDK,根据业务场景,发现针对 WebView 的大部分功能定制都是基于 WebView 的生命周期内发生的,所以参考 NodeJS 的中间件思想,设计了基于生命周期的 WebView 中间件):
#import <Foundation/Foundation.h>
@interface TPKTrustListHelper : NSObject
+(void)fetchRemoteTrustList;
+(BOOL)isHostInTrustlist:(NSString *)scheme;
+(NSArray *)trustList;
@end
测试类:
SPEC_BEGIN(TPKTrustListHelperTest)
describe(@"Middleware Wrapper", ^{
context(@"when get trustlist", ^{
it(@"should get a array of string",^{
NSArray *array = [TPKTrustListHelper trustList];
[[array shouldNot] beNil];
NSString *first = [array firstObject];
[[first shouldNot] beNil];
[[NSStringFromClass([first class]) should] equal:@"__NSCFString"];
});
});
context(@"when check a string wether contained in trustlist ", ^{
it(@"first string should contained in trustlist",^{
NSArray *array = [TPKTrustListHelper trustList];
NSString *first = [array firstObject];
[[theValue([TPKTrustListHelper isHostInTrustlist:first]) should] equal:@(YES)];
});
});
});
SPEC_END
例子包含 Kiwi 的最基础元素:
- SPEC_BEGIN 和 SPEC_END 表示测试类;
- describe 描述需要被测试的类;
- context 表示一个测试场景,也就是 Given->When->Then 里的 Given;
- it 表示要测试的内容,也就是也就是 Given->When->Then 里的 When 和 Then。
1个 describe 下可以包含多个 context,1个 context 下可以包含多个 it。
Kiwi 的使用分为:Specs、 Expectations 、 Mocks and Stubs 、Asynchronous Testing 四部分。
it 里面的代码块是真正的测试代码,使用链式调用的方式,简单上手。
测试领域中 Mock 和 Stub 非常重要。Mock 模拟对象可以降低对象之间的依赖,模拟出一个纯净的测试环境(类似初中物理课上“控制变量法”的思想)。
Kiwi 也支持得非常好,可以模拟对象、模拟空对象、模拟遵循协议的对象等等。
Stub 存根可以控制某个方法的返回值,这对于方法内调用别的对象的方法返回值很有帮助。减少对于外部的依赖,单一测试当前行为是否符合预期。
针对异步测试,XCTest 则需要创建一个 XCTestExpectation 对象,在异步实现里面调用该对象的 fulfill 方法。
最后设置最大等待时间和完成的回调 - (void)waitForExpectationsWithTimeout:(NSTimeInterval)timeout handler:(nullable XCWaitCompletionHandler)handler; 如下例子:
XCTestExpectation *exception = [self expectationWithDescription:@"测试数据库插入功能"];
[dbInstance removeAllLogsInTableType:HCTLogTableTypeMeta];
NSMutableArray *insertModels = [NSMutableArray array];
for (NSInteger index = 1; index <= 10000; index++) {
HCTLogMetaModel *model = [[HCTLogMetaModel alloc] init];
model.log_id = index;
// 。。。
[insertModels addObject:model];
}
[dbInstance add:insertModels inTableType:HCTLogTableTypeMeta];
[dbInstance recordsCountInTableType:HCTLogTableTypeMeta completion:^(NSInteger count) {
XCTAssert(count == insertModels.count, @"**Database「数据增加」功能:异常");
[exception fulfill];
}];
[self waitForExpectationsWithCommonTimeout];
expecta、Specta
expecta 和 Specta 都出自 orta 之手,他也是 Cocoapods 的开发者之一,太牛逼了,工程化、质量保证领域的大佬。
Specta 是一个轻量级的 BDD 测试框架,采用 DSL 模式,让测试更接近于自然语言,因此更易读。
特点:
-
易于集成到项目中。在 Xcode 中勾选 Include Unit Tests ,和 XCTest 搭配使用;
-
语法很规范,对比 Kiwi 和 Specta 的文档,发现很多东西都是相同的,也就是很规范,所以学习成本低、后期迁移到其他框架很平滑。
-
Expecta 是一个匹配(断言)框架,相比 Xcode 的断言 XCAssert,Excepta 提供更加丰富的断言。
特点:
-
Eepecta 没有数据类型限制,比如 1,并不关心是 NSInteger 还是 CGFloat;
-
链式编程,写起来很舒服;
-
反向匹配,很灵活,断言匹配用 except(…).to.equal(…),断言不匹配则使用 .notTo 或者 .toNot;
-
延时匹配,可以在链式表达式后加入 .will、.willNot、.after(interval) 等。
小结
Xcode 自带的 XCTestCase 比较适合 TDD,不影响源代码,系统独立且不影响 App 包大小,适合简单场景下的测试。
且每个函数在最左侧有个测试按钮,点击后可以单独测试某个函数。
Kiwi 是一个强大的 BDD 框架,适合稍微复杂些的项目,写法舒服、功能强大,模拟对象、存根语法、异步测试等满足几乎所有的测试场景。不能和 XCTest 继承。
Specta 也是一个 BDD 框架,基于 XCTest 开发,可以和 XCTest 模版集合使用。相比 Kiwi,Specta 轻量一些。开发中一般搭配 Excepta 使用。如果需要使用 Mock 和 Stud 可以搭配 OCMock。
Excepta 是一个匹配框架,比 XCTest 的断言则更加全面一些。
没办法说哪个最好、最合理,根据项目需求选择合适的组合。
技术行业要不断地学习,学习肯定不要孤军奋战,最好是能抱团取暖,相互成就一起成长,群众效应的效果是非常强大的,大家一起学习,一起打卡,会更有学习动力,也更能坚持下去。你可以加入我们的测试技术交流扣扣群:914172719(里面有各种软件测试资源和技术讨论)
送给大家一句话,共勉:当我们能力不足的时候,首先要做的是内修!当我们能力足够强大的时候,就可以外寻了!
最后也为大家准备了一份配套的学习资源,你可以微信扫描下方二维码,免费获取一份216页软件测试工程师面试宝典文档资料。以及相对应的视频学习教程免费分享!,其中资料包括了有基础知识、Linux必备、Shell、互联网程序原理、Mysql数据库、抓包工具专题、接口测试工具、测试进阶-Python编程、Web自动化测试、APP自动化测试、接口自动化测试、测试高级持续集成、测试架构开发测试框架、性能测试、安全测试等。
喜欢软件测试的小伙伴们,如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!
好文推荐
转行面试,跳槽面试,软件测试人员都必须知道的这几种面试技巧!
面试官:工作三年,还来面初级测试?恐怕你的软件测试工程师的头衔要加双引号…
4个月自学软件测试面进阿里!如何从功能测试转成自动化…我经历了什么
6000元报了培训班,3个月后我成功“骗”进了腾讯大厂,月薪15000