IOS unitTest 单元测试
2017-03-24 15:58
253 查看
测试驱动开发(TDD)是当前流行的开发理念,XCTest是Apple封装的单元测试类库。使用XCTest进行单元测试的流程比较简单,本博客仅简单介绍下XCTest的使用。但对于单元测试的理解(何时使用,如何更高效地驱动开发)却是一个需要积累的过程,要在TDD的过程中仔细体会。参考文章
创建项目的时候包含unitTest测试
然后可以看到下面文件
Baseline即可设置该性能是否合格的参考基准。
注意,一个性能测试case中只能执行一次measureBlock,即只能测试一个指定block步骤的性能(这其实也是合乎情理的,混到一块了哪里还能区分出性能测试的结果)。因此,在while,for等循环中是不能使用measureBlock的,否则会出错。
measureMetrics的用法跟measureBlock类似。
当然,也可以使用startMeasuring和stopMeasuring方法进行性能测试,但绝大多数情况下使用measureBlock已经足够了。
性能测试的宏定义
例如,在单独测试一个图片滤镜的性能时,可以这样
那么,如果有几十个滤镜需要进行性能测试呢?
因为单元测试case的方法名不能传递参数,且循环中不能使用measureBlock,因此对于大量重复的性能测试case,目前看来采用宏定义是比较好的解决方法。
则使用起来,就可如下定义所有的测试case了。
异步测试
XCTest提供了XCTestExpectation来进行异步测试,即可在指定时机使用其fulfill实例方法开始执行断言命令。例如以下是一个完整的网络请求的测试样例,可用于测试server端是否正常,要在对应的block中进行断言
即:异步网络请求操作正常执行,但断言命令仅在[expectation fulfill];结束后才开始执行,这样能确保得到网络请求的返回结果后执行相应断言。同时,可设置超时时间及对应操作。
否则,就需要使用定时机制等处理类似情况。
访问待测类的私有变量
在case中,如何访问一个待测类的私有变量呢?对该类进行相应的扩展即可。
FilterTool类的filterController属性和didSelectFilterCellAtIndexPath:方法本是私有的,若想对其进行测试,则必须将其加入扩展。
断言命令
XCTFail(format…) 生成一个失败的测试;
XCTAssertNil(a1, format…)为空判断,a1为空时通过,反之不通过;
XCTAssertNotNil(a1, format…)不为空判断,a1不为空时通过,反之不通过;
XCTAssert(expression, format…)当expression求值为TRUE时通过;
XCTAssertTrue(expression, format…)当expression求值为TRUE时通过;
XCTAssertFalse(expression, format…)当expression求值为False时通过;
XCTAssertEqualObjects(a1, a2, format…)判断相等,[a1 isEqual:a2]值为TRUE时通过,其中一个不为空时,不通过;
XCTAssertNotEqualObjects(a1, a2, format…)判断不等,[a1 isEqual:a2]值为False时通过,
XCTAssertEqual(a1, a2, format…)判断相等(当a1和a2是 C语言标量、结构体或联合体时使用,实际测试发现NSString也可以);
XCTAssertNotEqual(a1, a2, format…)判断不等(当a1和a2是 C语言标量、结构体或联合体时使用);
XCTAssertEqualWithAccuracy(a1, a2, accuracy, format…)判断相等,(double或float类型)提供一个误差范围,当在误差范围(+/-accuracy)以内相等时通过测试;
XCTAssertNotEqualWithAccuracy(a1, a2, accuracy, format…) 判断不等,(double或float类型)提供一个误差范围,当在误差范围以内不等时通过测试;
XCTAssertThrows(expression, format…)异常测试,当expression发生异常时通过;反之不通过;(很变态)
XCTAssertThrowsSpecific(expression, specificException, format…) 异常测试,当expression发生specificException异常时通过;反之发生其他异常或不发生异常均不通过;
XCTAssertThrowsSpecificNamed(expression, specificException, exception_name, format…)异常测试,当expression发生具体异常、具体异常名称的异常时通过测试,反之不通过;
XCTAssertNoThrow(expression, format…)异常测试,当expression没有发生异常时通过测试;
XCTAssertNoThrowSpecific(expression, specificException, format…)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过;
XCTAssertNoThrowSpecificNamed(expression, specificException, exception_name, format…)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过.
创建项目的时候包含unitTest测试
然后可以看到下面文件
// // TestUIandUnitTests.m // TestUIandUnitTests // // Created by BOB on 17/3/23. // Copyright © 2017年 BOB. All rights reserved. // #import <XCTest/XCTest.h> @interface TestUIandUnitTests : XCTestCase @end @implementation TestUIandUnitTests //处理用例执行前的准备工作 - (void)setUp { [super setUp]; // Put setup code here. This method is called before the invocation of each test method in the class. } //执行完毕后的清理工作 - (void)tearDown { // Put teardown code here. This method is called after the invocation of each test method in the class. [super tearDown]; } //所有以test开头的实例方法(不能有参数)都是一个完整的单元测试的case - (void)testExample { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. XCTAssert(YES,@"Pass"); } - (void)testPerformanceExample { // This is an example of a performance test case. [self measureBlock:^{ // Put the code you want to measure the time of here. }]; } /* 性能测试可直接使用 - (void)measureBlock:(void (^)(void))block; 进行,传递参数即为要执行任务组成的一个block。 注意,一个性能测试case中只能执行一次measureBlock,即只能测试一个指定block步骤的性能(这其实也是合乎情理的,混到一块了哪里还能区分出性能测试的结果)。因此,在while,for等循环中是不能使用measureBlock的,否则会出错。 measureMetrics的用法跟measureBlock类似。 当然,也可以使用startMeasuring和stopMeasuring方法进行性能测试,但绝大多数情况下使用measureBlock已经足够了。 */ @end
Baseline即可设置该性能是否合格的参考基准。
注意,一个性能测试case中只能执行一次measureBlock,即只能测试一个指定block步骤的性能(这其实也是合乎情理的,混到一块了哪里还能区分出性能测试的结果)。因此,在while,for等循环中是不能使用measureBlock的,否则会出错。
measureMetrics的用法跟measureBlock类似。
当然,也可以使用startMeasuring和stopMeasuring方法进行性能测试,但绝大多数情况下使用measureBlock已经足够了。
性能测试的宏定义
例如,在单独测试一个图片滤镜的性能时,可以这样
- (void)testPerformanceFilter1 { [self measureBlock:^{ NSInteger filterid = 100; UIImage *filteredImage = [FilterTool filterImage:self.image withFilterId:filterid]; XCTAssertNotNil(filteredImage, @"滤镜效果图应该非空"); }]; }
那么,如果有几十个滤镜需要进行性能测试呢?
因为单元测试case的方法名不能传递参数,且循环中不能使用measureBlock,因此对于大量重复的性能测试case,目前看来采用宏定义是比较好的解决方法。
#define TestFilterPerformance(filterid) - (void)testFilterPerformance_##filterid { \ [self measureBlock:^{ \ UIImage *filteredImage = [FilterTool filterImage:self.image withFilterId:filterid]; \ XCTAssertNotNil(filteredImage, @"滤镜效果图应该非空"); \ }]; \ }
则使用起来,就可如下定义所有的测试case了。
异步测试
XCTest提供了XCTestExpectation来进行异步测试,即可在指定时机使用其fulfill实例方法开始执行断言命令。例如以下是一个完整的网络请求的测试样例,可用于测试server端是否正常,要在对应的block中进行断言
- (void)testAsynchronousURLConnection { XCTestExpectation *expectation = [self expectationWithDescription:@"GET Baidu"]; NSURL *url = [NSURL URLWithString:@"http://www.baidu.com/"]; NSURLSession *session = [NSURLSession sharedSession]; NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { // XCTestExpectation条件已满足,接下来的测试可以执行了。 [expectation fulfill]; XCTAssertNotNil(data, @"返回数据不应非nil"); XCTAssertNil(error, @"error应该为nil"); if (nil != response) { NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; XCTAssertEqual(httpResponse.statusCode, 200, @"HTTPResponse的状态码应该是200"); XCTAssertEqual(httpResponse.URL.absoluteString, url.absoluteString, @"HTTPResponse的URL应该与请求的URL一致"); } else { XCTFail(@"返回内容不是NSHTTPURLResponse类型"); } }]; [task resume]; // 超时后执行 [self waitForExpectationsWithTimeout:10 handler:^(NSError * _Nullable error) { [task cancel]; }]; }
即:异步网络请求操作正常执行,但断言命令仅在[expectation fulfill];结束后才开始执行,这样能确保得到网络请求的返回结果后执行相应断言。同时,可设置超时时间及对应操作。
否则,就需要使用定时机制等处理类似情况。
访问待测类的私有变量
在case中,如何访问一个待测类的私有变量呢?对该类进行相应的扩展即可。
#import #import "FilterTool.h" @interface FilterTool (UnitTest) @property (strong, nonatomic) FilterController *filterController; - (void)didSelectFilterCellAtIndexPath:(NSIndexPath *)indexPath; @end @interface FilterToolTest : XCTestCase @end @implementation FilterToolTest XXXX @end
FilterTool类的filterController属性和didSelectFilterCellAtIndexPath:方法本是私有的,若想对其进行测试,则必须将其加入扩展。
断言命令
XCTFail(format…) 生成一个失败的测试;
XCTAssertNil(a1, format…)为空判断,a1为空时通过,反之不通过;
XCTAssertNotNil(a1, format…)不为空判断,a1不为空时通过,反之不通过;
XCTAssert(expression, format…)当expression求值为TRUE时通过;
XCTAssertTrue(expression, format…)当expression求值为TRUE时通过;
XCTAssertFalse(expression, format…)当expression求值为False时通过;
XCTAssertEqualObjects(a1, a2, format…)判断相等,[a1 isEqual:a2]值为TRUE时通过,其中一个不为空时,不通过;
XCTAssertNotEqualObjects(a1, a2, format…)判断不等,[a1 isEqual:a2]值为False时通过,
XCTAssertEqual(a1, a2, format…)判断相等(当a1和a2是 C语言标量、结构体或联合体时使用,实际测试发现NSString也可以);
XCTAssertNotEqual(a1, a2, format…)判断不等(当a1和a2是 C语言标量、结构体或联合体时使用);
XCTAssertEqualWithAccuracy(a1, a2, accuracy, format…)判断相等,(double或float类型)提供一个误差范围,当在误差范围(+/-accuracy)以内相等时通过测试;
XCTAssertNotEqualWithAccuracy(a1, a2, accuracy, format…) 判断不等,(double或float类型)提供一个误差范围,当在误差范围以内不等时通过测试;
XCTAssertThrows(expression, format…)异常测试,当expression发生异常时通过;反之不通过;(很变态)
XCTAssertThrowsSpecific(expression, specificException, format…) 异常测试,当expression发生specificException异常时通过;反之发生其他异常或不发生异常均不通过;
XCTAssertThrowsSpecificNamed(expression, specificException, exception_name, format…)异常测试,当expression发生具体异常、具体异常名称的异常时通过测试,反之不通过;
XCTAssertNoThrow(expression, format…)异常测试,当expression没有发生异常时通过测试;
XCTAssertNoThrowSpecific(expression, specificException, format…)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过;
XCTAssertNoThrowSpecificNamed(expression, specificException, exception_name, format…)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过.
相关文章推荐
- IOS-使用XCODE自带的单元测试UnitTest
- iOS开发 简述使用OCUnit对程序进行单元测试(UnitTest)
- 单元测试(UnitTest)入门
- C++ 单元测试工具 CppUnitTest
- 用CL_AUNIT_ASSERT 类进行ABAP单元测试 ABAP Unit TEST
- 使用 Visual Studio 2005 Team System 进行单元测试并生成用于 Unit Test Framework 的源代码(详解)
- 单元测试技术(Unit Test)
- 使用 Visual Studio 2005 Team System 进行单元测试并生成用于 Unit Test Framework 的源代码
- C++ Unit Test Framework(单元测试框架)
- python中的单元测试pyUnit & what is unit test and why
- C/C++单元测试框架的选择(CppUTest vs. CppUnit vs. CppUnitLite vs. CppTest vs. GoogleTest vs. CxxTest vs. CUnit)
- c语言实现一个单元测试框架(Unit Test Framework)代码
- 使用 Visual Studio 2005 Team System 进行单元测试并生成用于 Unit Test Framework 的源代码
- 使用 Visual Studio 2005 Team System 进行单元测试并生成用于 Unit Test Framework 的源代码 (实例) (轉載)
- 单元测试(Unit Test) 之大小
- 单元测试(Unit Test) 之大小
- 使用 Visual Studio 2005 Team System 进行单元测试并生成用于 Unit Test Framework 的源代码
- 使用 Visual Studio 2005 Team System 进行单元测试并生成用于 Unit Test Framework 的源代码
- 单元测试(Unit Test) 之大小
- 单元测试(UnitTest)入门