作为第二代敏捷方法,BDD提倡的是通过将测试语句转换为雷同天然语言的形貌,开发职员可以利用更符合大众语言的风俗来誊写测试,如许岂论在项目交接/交付,大概之后自己修改时,都可以顺遂很多。假如说作为开发者的我们一样平常工作是写代码,那么BDD实在就是在讲故事。一个典型的BDD的测试用例包活完备的三段式上下文,测试大多可以翻译为Given..When..Then的格式,读起来轻松惬意。BDD在其他语言中也已经有一些框架,包罗最早的Java的JBehave和赫赫闻名的Ruby的RSpec和Cucumber。而在objc社区中BDD框架也正在欣欣向荣地发展,得益于objc的语法原来就非常靠近天然语言,再加上C语言宏的威力,我们是有大概写出美丽精致的测试的。在objc中,如今比力盛行的BDD框架有cedar,specta和Kiwi。本文紧张先容的是Kiwi,利用Kiwi写出的测试看起来大概会是这个样子的:
示比方下所示:
describe(@"Team", ^{ context(@"when newly created", ^{ it(@"has a name", ^{ id team = [Team team]; [[team.name should] equal"Black Hawks"]; }); it(@"has 11 players", ^{ id team = [Team team]; [[[team should] have:11] players]; }); });});我们很容易根据上下文将其提取为Given..When..Then的三段式天然语言
Given a team, when newly created, it should have a name, and should have 11 players很简朴啊有木有!在如许的语法下,是不是写测试的爱好都被引发出来了呢。关于Kiwi的进一步语法和利用,我们稍后具体睁开。起首来看看如安在项目中添加Kiwi框架吧。
可以通过通过CocoaPods安装,请将此添加到您的Podfile:
pod "Kiwi"二、Kiwi的利用
点击下载Demo:ZJHUnitTestDemo
2.1、Kiwi测试的基本布局
可以直接创建一个平常的Objective-C test case class,如:ZJHFirstKiwiTests,然后再内里添加Kiwi代码:
#import "Kiwi.h"SPEC_BEGIN(SimpleStringSpec)describe(@"SimpleString", ^{ context(@"when assigned to 'Hello world'", ^{ NSString *greeting = @"Hello world"; it(@"should exist", ^{ [[greeting shouldNot] beNil]; }); it(@"should equal to 'Hello world'", ^{ [[greeting should] equal"Hello world"]; }); });});SPEC_END你大概会以为这不是objc代码,甚至猜疑这些语法是否可以或许编译通过。实在SPEC_BEGIN和SPEC_END都是宏,它们界说了一个KWSpec的子类,并将其中的内容包装在一个函数中(有爱好的朋侪不妨点进去看看)。
describe形貌必要测试的对象内容,也即我们三段式中的Given,context形貌测试上下文,也就是这个测试在When来举行,末了it中的是测试的本体,形貌了这个测试应该满意的条件,三者共同构成了Kiwi测试中的举动形貌。它们是可以nest的,也就是一个Spec文件中可以包罗多个describe(固然我们很少这么做,一个测试文件应该专注于测试一个类);一个describe可以包罗多个context,来形貌类在差异情形下的举动;一个context可以包罗多个it的测试例。让我们运行一下这个测试,观察输出:
ZJHUnitTestDemo[14459:288758] + 'SimpleString, when assigned to 'Hello world', should exist' [PASSED]ZJHUnitTestDemo[14459:288758] + 'SimpleString, when assigned to 'Hello world', should equal to 'Hello world'' [PASSED]2.2、Kiwi规则
先看下面的第二个示例子代码
#import "Kiwi.h"#import "ZJHKiwiSample.h"// SPEC_BEGIN(ClassName) 和 SPEC_END 宏,用于标志 KWSpec 类的开始和竣事,以及测试用例的分组声明SPEC_BEGIN(ZJHKiwiSampleSpec)describe(@"ZJHKiwiSample Kiwi test", ^{ registerMatchers(@"ZJH"); // 注册全部利用"ZJH"定名空间前缀的匹配器. context(@"a state the component is in", ^{ let(variable, ^{ // 在每个包罗的 "it" 实行前实行实行一次. return [[ZJHKiwiSample alloc]init]; }); beforeAll(^{ // 在全部内嵌上下文或当前上下文的 it block实行之前实行一次. NSLog(@"beforAll"); }); afterAll(^{ // 在全部内嵌上下文或当前上下文的 it block实行之后实行一次. NSLog(@"afterAll"); }); beforeEach(^{ // 在全部包罗的上下文情况的 it block实行之前,均各实行一次.用于初始化指定上下文情况的代码 NSLog(@"beforeEach"); }); afterEach(^{ // 在全部包罗的上下文情况的 it block实行之后,均各实行一次. NSLog(@"afterEach"); }); it(@"should do something", ^{ // 声明一个测试用例.这里形貌了对对象或举动的渴望. NSLog(@"should do something"); }); specify(^{ // 可用于标志尚未完成的功能或用例,仅会使Xcode输出一个黄色告诫 NSLog(@"specify"); [[variable shouldNot] beNil]; }); context(@"inner context", ^{ // 可以嵌套context NSLog(@"inner context"); it(@"does another thing", ^{ NSLog(@"does another thing"); }); pending(@"等候实现的东西", ^{ // 可用于标志尚未完成的功能或用例,仅会使Xcode输出一个黄色告诫 NSLog(@"等候实现的东西"); }); }); });});SPEC_END