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 的断言则更加全面一些。
没办法说哪个最好、最合理,根据项目需求选择合适的组合。
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理 本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理