内容简介:单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如 C 语言中单元指一个函数,Java 里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。1)在一个复杂的项目中添加某功能模块时,可以快捷的进行针对性测试,而不用将整个项目 Run 起来。
单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如 C 语言中单元指一个函数,Java 里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。
单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。
为什么要做单元测试
1)在一个复杂的项目中添加某功能模块时,可以快捷的进行针对性测试,而不用将整个项目 Run 起来。
2)可以便捷的对某个具体方法进行测试。
单元测试有哪些
iOS 开发(或者 MacOS、tvOS、watchOS 等)中,单元测试有多种方式,主要分为 Xcode 提供的以及第三方测试框架这两类:
-
Xcode自带 XCTest:XCTest 是 Xcode自带的单元测试工具,其前身是 OCUnit,随着 Xcode 的发展,XCTest 已经越来越完善,功能也越强大。
-
第三方框架 GHUnit:GHUnit 是 GitHub 上著名的开源测试框架,可视化、开源、扩展等功能,让其相比 XCTest 更加强大(现在的 XCTest 也很完善了,不过 GHUnit 比较老,现在已经停止维护,不建议使用) OCMock:OCMock 也是 Github 上的著名开源测试框架,用于 Mock、Stub,为测试提供数据作假功能。
以上三种就是比较主流的测试 Xcode 单元测试途径,还有一些 BDD 行为测试框架:
什么是 BDD BDD(Behavior Driven Development),即行为驱动开发,是敏捷开发技术之一,通过自然语言定义系统行为,以功能使用者的角度,编写需求场景,且这些行为描述可以直接形成需求文档,同时也是测试标准。
- Specta:GitHub 上轻量级的 BDD 测试框架。
- Expecta:与 Specta 同个作者,是一个功能强大的匹配框架。
- Kiwi:Kiwi 是重量级的,集 OCMock、Specta、Expecta 所拥有的功能与一身的 BDD DSL 测试框架。
其他的,还有一些其他测试 工具 、测试方式,如:
- Nocilla:强大的 HTTP 模拟测试工具。
- OHHTTPStubs:也是 HTTP 模拟测试工具。
- TUDelorean:基于 Objective-C 的时间模拟测试工具。
- KIF:集成/界面测试工具,其它的还有 Frank、Calabash 等。
- GitHub + Jenkins + TestFlight:自动化测试。
- Monkey Test:随机测试。
XCTest 测试
1、创建测试类
注意,所有测试类都继承自 XCTestCase。
2、测试类的结构
默认创建的单元测试类为一个 .m
文件,里面包含了以下四个方法:
- (void)setUp - (void)tearDown - (void)testExample - (void)testPerformanceExample
3、测试流程
当我们默认执行测试时,系统找到所有的测试类,并执行每个测试方法;我们也可以选择性地执行某些测试而已,比如,在 scheme 中 disable 某个用例,或者直接在测试导航栏中每个测试用例后面的运行按钮,单独执行某个测试。
默认流程如下:
上一个测试类 -> 当前类 + (void)setUp
-> [ - (void)setUp
-> 测试方法 -> - (void)tearDown
] (循环直至当前类测试方法全部执行完) -> 当前类 + (void)tearDown
-> 下一个测试类
4、测试方法
测试方法以 test 为前缀,没有参数,返回值为 void,方法中用断言来判断测试的正确性:
- (void)testColorIsRed { // Set up, call test subject API. (Code could be shared in setUp method.) // Test logic and values, assertions report pass/fail to testing framework. // Tear down. (Code could be shared in tearDown method. } - (void)testThatItDoesURLEncoding { // given NSString *searchQuery = @"$content$amp;?@"; HTTPRequest *request = [HTTPRequest requestWithURL:@"/search?q=%@", searchQuery]; // when NSString *encodedURL = request.URL; // then XCTAssertEqualObjects(encodedURL, @"/search?q=%24%26%3F%40"); }
5、测试断言
断言一般由判断条件、字符串 format、字符串参数组成,参数可选,在 XCTest 中,断言有以下分类:
- Unconditional Fail:XCTFail,失败时候抛出。
- Equality Tests:用于断言两个表达式相等或不相等,如:XCTAssertEqual、XCTAssertEqualWithAccuracy、XCTAssertNotEqual、 XCTAssertGreaterThan。
- Boolean Tests:断言布尔表达式真假,如:XCTAssertTrue、XCTAssertFalse。
- Nil Tests:空断言,如:XCTAssertNil、XCTAssertNotNil。
- Exception Tests:断言表达式抛出或不抛出异常,如:XCTAssertThrows、XCTAssertThrowsSpecific、XCTAssertNoThrow。
Specta、Expecta 测试
Specta 和 Expecta 都是出自 Github 作者 Orta 之手,他最出名的开源框架莫过于 Cocoapods 。
Specta
Specta 是一个轻量级 BBD 测试框架,其为 DSL (Domain-Specific Language) 模式,让测试更加接近于自然语言描述,更加易懂。
1、主要有以下特点:
- 容易集成到项目中。
- 基于XCTest编写,可以很好地与XCTest配合使用。
2、语法介绍
1) SpecBegin 声明了一个测试类,SpecEnd 结束类声明
2) describe (context) 块声明了一组实例
3) it (example/specify) 是一个单一的样例
4) beforeAll 是一个执行于全部同级块之前的块,仅仅执行一次。afterAll 与beforeAll相反,是在全部同级块之后执行的块。仅仅执行一次。
5) beforeEach/afterEach,在每一个同级块执行的时候,都会执行一次,而beforeAll/afterAll仅仅会执行一次
6) it/waitUntil/done()。异步调用,注意完毕异步操作之后。必须调用done()函数。例如以下:
it(@"should do some stuff asynchronously", ^{ waitUntil(^(DoneCallback done) { // Async example blocks need to invoke done() callback. done(); }); });
7) sharedExamplesFor 和 itShouldBehaveLike结合在一起。能够实如今不同的spec之间共享同一套test case sharedExamplesFor 设置多个spec之间共享的test case,第一个參数作为标识符。通过itShouldBehaveLike来执行spec中test case。第一个參数传入sharedExamplesFor设置时使用的标识符。
注意:在describe局部使用sharedExamplesFor定义shared examples。能够在它作用域内覆盖全局的shared examples。
8) pending,仅仅打印一条log信息。不做测试。这个语句会给出一条警告,能够作为一开始集中书写行为描写叙述时还未实现的测试的提示。
3、一般使用:
SpecBegin(Car) describe(@"Car", ^{ __block Car *car; // Will be run before each enclosed it beforeEach(^{ car = [Car new]; }); // Will be run after each enclosed it afterEach(^{ car = nil; }); // An actual test it(@"should be red", ^{ expect(car.color).to.equal([UIColor redColor]); }); describe(@"when it is started", ^{ beforeEach(^{ [car start]; }); it(@"should have engine running", ^{ expect(car.engine.running).to.beTruthy(); }); }); describe(@"move to", ^{ context(@"when the engine is running", ^{ beforeEach(^{ car.engine.running = YES; [car moveTo:CGPointMake(42,0)]; }); it(@"should move to given position", ^{ expect(car.position).to.equal(CGPointMake(42, 0)); }); }); context(@"when the engine is not running", ^{ beforeEach(^{ car.engine.running = NO; [car moveTo:CGPointMake(42,0)]; }); it(@"should not move to given position", ^{ expect(car.engine.running).to.beTruthy(); }); }); }); }); SpecEnd
上面例子对 Car 这个类做测试,通过多个上下文嵌套(describe/context),结合不同的条件(beforeEach),来作出不同的断言(it);当我们某个测试失败时,我们会收到一段很明确的错误信息,比如:汽车启动后应该移动到指定位置这个用例测试失败,那么我们会收到 Car move to when the engine is running should move to given position 这么一段话。这样非常接近自然语言的描述会让我们很快知道错误出在哪里。
4、注意:
-
如果想用 SPEC_BEGIN 和 SPEC_END 替代 SpecBegin and SpecEnd,应该在引入头文件之前写上 #define SPT_CEDAR_SYNTAX
-
如果要使用 XCTest Resporter,那么在 Test Scheme 中,把 SPTXCTestReporter 字段值改为 SPECTA_REPORTER_CLASS
-
把环境变量 SPECTA_SHUFFLE 设置为 1 启用测试拖拽(test shuffling)
Expecta
Expecta 是基于 Objective-C/Cocoa 的断言框架,XCTest 自带的断言 XCAssert 有好几个基础操作,不过基础的断言不太丰富,和 Specta 也没有很适配。 Expecta 不一样,将匹配过程从断言中剥离开,可以很好地适配 Specta 的 DSL 断言块。
1、Expecta 有以下几个特点:
-
没有类型限制,比如数值 1,并不用关心它是整形还是浮点数
-
链式编程,可读性高,如:expect(foo).notTo.equal(1)
-
反向匹配,断言不匹配只需加上 .notTo 或者 .toNot,如:expect(x).notTo.equal(y)
-
延时匹配,可以在链式表达式中加入 .will、.willNot、.after(interval) 等操作来延时匹配
-
可扩展,支持增加自定义匹配
2、基础匹配 API:
expect(x).to.equal(y); // x 与 y 相等 expect(x).to.beIdenticalTo(y); // x 与 y 相等且内存地址相同 expect(x).to.beNil(); // x 为 nil expect(x).to.beTruthy(); // x 为 true(非 0) expect(x).to.beFalsy(); // x 为 false(0 值)
3、异步匹配
describe(@"WebImage", ^{ beforeAll(^{ // 设置默认延时匹配时间 [Expecta setAsynchronousTestTimeout:2]; }); it(@"will not be nil", ^{ // 使用默认延时匹配 expect(webImage).willNot.beNil(); }); it(@"should equal 42 after 3 seconds", ^{ // 不使用默认延时匹配,手动设置为3秒 expect(webImage).after(3).to.equal(42); }); });
4、自定义使用
#import <Specta/Specta.h> #import <Expecta/Expecta.h> #import "ImageModel.h" SpecBegin(ImageModel); __block ImageModel *model; beforeEach(^{ model = [[ImageModel alloc] initWithUrl:@"http://pic37.nipic.com/20140113/8800276_184927469000_2.png" title:@"天空独角马" described:@"在黄色的沙漠里,特别突兀"]; }); it(@"should not nil", ^{ expect(model).toNot.beNil(); }); it(@"equal", ^{ expect(model.url).to.equal(@"http://pic37.nipic.com/20140113/8800276_184927469000_2.png"); expect(model.title).to.equal(@"天空独角马"); expect(model.described).to.equal(@"在黄色的沙漠里,特别突兀"); }); SpecEnd;
总结
Expecta 和 Specta 需要配合使用,与 XCTest 一样都是基于 XCTestCase 实现。在断言的使用上,XCTest 太过死板,Expecta 和 Specta 则很灵活,可以满足大部分场景需求。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Vue 应用单元测试的策略与实践 02 - 单元测试基础
- Vue 应用单元测试的策略与实践 04 - Vuex 单元测试
- Vue 应用单元测试的策略与实践 03 - Vue 组件单元测试
- Angular单元测试系列-Component、Directive、Pipe 以及Service单元测试
- 单元测试,只是测试吗?
- 单元测试和集成测试业务
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Head First HTML and CSS
Elisabeth Robson、Eric Freeman / O'Reilly Media / 2012-9-8 / USD 39.99
Tired of reading HTML books that only make sense after you're an expert? Then it's about time you picked up Head First HTML and really learned HTML. You want to learn HTML so you can finally create th......一起来看看 《Head First HTML and CSS》 这本书的介绍吧!