iOS —— 单元测试(一) 电玩女神 2022-03-20 14:10 285阅读 0赞 # 目录 # * 一、简介 * 二、苹果自带的XCTest # 一、简介 # # # 单元测试是指开发者编写代码,去验证被测代码是否正确的一种手段,其实就是用代码去检测代码。合理的利用单元测试可以提高软件的质量。 # 二、苹果自带的XCTest # # # 1.创建我们的工程,勾选 `Include Unit Tests` ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MTQ2Mzk3MQ_size_16_color_FFFFFF_t_70] 2.创建单元测试类 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MTQ2Mzk3MQ_size_16_color_FFFFFF_t_70 1] 3.命名和继承的父类 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MTQ2Mzk3MQ_size_16_color_FFFFFF_t_70 2] `UserInfoModelTest.m`中的代码: + (void)setUp { [super setUp]; } + (void)tearDown { [super tearDown]; } // 单元测试开始前调用 - (void)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. } // 测试代码可以写到以test开头的方法中 并且test开头的方法左边会生成一个菱形图标,点击即可运行检测当前test方法内的代码 - (void)testExample { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests produce the correct results. // 测试的基本结构,三段式 // 1、Given 创造测试条件。数据初始化的对象,值。可以使用 OCMock 三方库。 UserInfoModel *userInfoModel = [UserInfoModel new]; // 2、When 测试方法的参数 userInfoModel.age = @10; // 模拟合法年龄( 0 < age < 80 认为是合法年龄) // 3、Then 断言,是否符合预期 XCTAssert(userInfoModel.age.integerValue > 0, "姓名大于0 - 合法"); XCTAssert(userInfoModel.age.integerValue < 80, "姓名小于80 - 合法"); } // 测试性能 - (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)testXXX`方式命名。 我们一起看一下方法的调用顺序,可以使用快捷键 `command + U` 1. 先调用 `+ (void)setUp`方法,加载我们的测试类 2. 调用`- (void)setUp`,单元测试开始前调 3. 调用`- (void)testExample`,测试代码可以写到以test开头的方法中 并且test开头的方法左边会生成一个菱形图标,点击即可运行检测当前test方法内的代码; 4. 调用`- (void)tearDown`,单元测试结束前调用; 5. 调用`- (void)setUp`,重置对象等的信息,继续测试 6. 调用`- (void)testPerformanceExample`,测试性能 7. 调用`- (void)tearDown` 8. 最后调用 `+ (void)tearDown` 我们可以看到 `- (void)setUp`、`- (void)tearDown`会重复调用,分别表示测试开始重置对象或数据,测试结束。 另外,测试代码可以写到以 `test`开头的方法中 并且 `test`开头的方法左边会生成一个菱形图标(如下图),点击即可运行检测当前test方法内的代码。 ![菱形图标][20190213110858795.png] `test`方法中的代码一般为三段式结构,如上代码。 下面我们模拟对 `UserInfoMode`类中的 age 属性进行测试,具体实现可以看上面的代码。 ![测试通过][20190213111152325.png] ![测试未通过][2019021311123962.png] 我们主要是设置一些 `断言`,来判断代码是否符合我们的预期,是否符合逻辑。 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没有发生具体异常、具体异常名称的异常时通过测试,反之不通过 以上是XCTest的基本用法,下面我们说一下`- (void)testPerformanceExample`性能测试。将要测试执行时间的代码放到 block 块内 // 测试性能 - (void)testPerformanceExample { NSLog(@"%s", __func__); // This is an example of a performance test case. [self measureBlock:^{ // Put the code you want to measure the time of here. NSMutableArray *testArray = [[NSMutableArray alloc] init]; for (int i = 0; i < 10000; i ++) { NSObject *obj = [[NSObject alloc] init]; [testArray addObject:obj]; } }]; } 控制台输出结果: Test Case '-[UserInfoModelTest testPerformanceExample]' measured [Time, seconds] average: 0.015, relative standard deviation: 61.727%, values: [0.003263, 0.022181, 0.019327, 0.002817, 0.023823, 0.004887, 0.026164, 0.022138, 0.004508, 0.021344], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100 从这里我们可以获知在一个for循环重复的代码,程序会运行10次,取一个平均运行时间值,average: 0.015这个就是平均时间0.015秒。 现在我们知道了测量一个函数的运行时间,到底这个函数效率高不高可以使用testPerformanceExample方法,但是在这之前我们怎么测试函数性能呢?我们可以使用NSTimeInterval来做,根据时间差的打印来分析,具体用法如下代码: // 测试性能 - (void)testPerformanceExample { [self measureBlock:^{ // CACurrentMediaTime() 是手机从开机一直到当前所经过的秒数。 NSTimeInterval startTime = CACurrentMediaTime(); NSMutableArray * mutArray = [[NSMutableArray alloc] init]; for (int i = 0; i < 10000; i++) { NSObject * object = [[NSObject alloc] init]; [mutArray addObject:object]; } NSLog(@"耗时:%f",CACurrentMediaTime() - startTime); }]; } 输出结果: > 2019-02-13 12:49:36.298823+0800 CocoapodsDemo\[7824:2125978\] 耗时:0.031548 > 2019-02-13 12:49:36.335230+0800 CocoapodsDemo\[7824:2125978\] 耗时:0.033513 > 2019-02-13 12:49:36.363585+0800 CocoapodsDemo\[7824:2125978\] 耗时:0.001930 > 2019-02-13 12:49:36.382447+0800 CocoapodsDemo\[7824:2125978\] 耗时:0.017103 > 2019-02-13 12:49:36.401863+0800 CocoapodsDemo\[7824:2125978\] 耗时:0.017622 > 2019-02-13 12:49:36.421803+0800 CocoapodsDemo\[7824:2125978\] 耗时:0.017795 > 2019-02-13 12:49:36.444744+0800 CocoapodsDemo\[7824:2125978\] 耗时:0.020235 > 2019-02-13 12:49:36.466671+0800 CocoapodsDemo\[7824:2125978\] 耗时:0.019422 > 2019-02-13 12:49:36.487286+0800 CocoapodsDemo\[7824:2125978\] 耗时:0.018172 > 2019-02-13 12:49:36.506918+0800 CocoapodsDemo\[7824:2125978\] 耗时:0.001468 参考: [浅谈iOS单元测试][iOS] [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MTQ2Mzk3MQ_size_16_color_FFFFFF_t_70]: /images/20220320/4defdabde97a40de8b1b3021e64b8a5b.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MTQ2Mzk3MQ_size_16_color_FFFFFF_t_70 1]: /images/20220320/c5e67baada7040b1874f7c2135bc07c8.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MTQ2Mzk3MQ_size_16_color_FFFFFF_t_70 2]: /images/20220320/5a8cb9bfb0474d1dac82720a21de67d2.png [20190213110858795.png]: /images/20220320/01d5ce5d3f7042caaade12a98090bf2a.png [20190213111152325.png]: /images/20220320/b3b86190c802473f826e78ce5b216bb3.png [2019021311123962.png]: /images/20220320/c120ca0735254e8fbf7a9ce3583b66a0.png [iOS]: https://www.jianshu.com/p/1e8d6885d517
还没有评论,来说两句吧...