初探iOS单元测试XCTest

测试基本流程

添加单元测试

  1. 创建项目时勾选Inclue Unit Tests .
  2. 忘了勾选可通过创建File–>new–>target–>iOS–>iOS Unit Testing Bundle。

默认单元测试文件

继承XCTestCase,默认的方法有4个:
1. setUp(每个测试方法调用前执行, 在执行完父类方法后添加自定义配置);
2. tearDown(每个测试方法调用后执行,在执行父类方法前添加自定义配置);
3. textExample(一个示例);
4. testPerformanceExample(在measureBlock中放入需要测试性能的代码)方法。

添加测试用例

测试用例命名必须以test开头,不可有参数且返回为void,不然无法识别为测试方法。测试用例类型有3种:普通测试,性能测试与异步测试。在后文中有详细介绍

运行单元测试

  1. 运行单元测试快捷键: CMD + U测试整个文件的测试用例
  2. 也可通过每个单元测试用例左边的按钮执行单元测试,执行后绿色勾选按钮代表测试成功,红色叉号按钮代表测试失败。

测试用例类型

普通测试

如果代码未返回预测结果,则通过断言API打印错误。

// 1. 普通测试
- (void)testExample {
    // This is an example of a functional test case.
    // Use XCTAssert and related functions to verify your tests produce the correct results.
    NSLog(@"testExample");
    int a = 0;
    XCTAssertTrue(a == 0, "断言a等于0,不等于则测试没通过");
}

常用断言如下所示(以下断言含义from ios UnitTest 学习笔记):

// 常用断言
XCTAssert(expression, format...)当expression求值为TRUE时通过;
XCTAssertTrue(expression, format...)当expression求值为TRUE时通过;
XCTAssertFalse(expression, format...)当expression求值为False时通过;

XCTAssertNil(a1, format...)为空判断,a1为空时通过,反之不通过;
XCTAssertNotNil(a1, format…)不为空判断,a1不为空时通过,反之不通过;
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发生异常时通过;反之不通过;(很变态)

XCTAssertThrowsSpecificNamed(expression, specificException, exception_name, format...)异常测试,当expression发生具体异常、具体异常名称的异常时通过测试,反之不通过;
XCTAssertNoThrow(expression, format…)异常测试,当expression没有发生异常时通过测试;
XCTAssertNoThrowSpecific(expression, specificException, format...)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过;
XCTAssertNoThrowSpecificNamed(expression, specificException, exception_name, format...)异常测试,当expression没有发生具体异常、具体异常名称的异常时通过测试,反之不通过
// 非常用断言
XCTFail(format…) 生成一个失败的测试;
XCTAssertThrowsSpecific(expression, specificException, format...) 异常测试,当expression发生specificException异常时通过;反之发生其他异常或不发生异常均不通过;

ps:
?1. XCTAssert与XCTAssertTrue有什么区别

?2. XCTAssertEqualObjects和XCTAssertEqual有什么区别
[reply]XCTAssertEqualObjects(a1, a2, format…)的判断条件是[a1 isEqual:a2]是否返回一个YES。XCTAssertEqual(a1, a2, format…)的判断条件是a1 == a2是否返回一个YES,如果a1和a2都是基本数据类型变量,那么只有a1 == a2才会返回YES;如果a1和a2都是指针,那么只有a1和a2指向同一个对象才会返回YES。

性能测试

// 2. 性能测试
- (void)testPerformanceExample {
    // This is an example of a performance test case.
    [self measureBlock:^{// 运行测试后,该行会显示执行时间,block内放入需测试性能的代码块
        // Put the code you want to measure the time of here.
        for (int i = 0; i < 100; i++) {
            NSLog(@"dd");
        }
    }];
}

异步测试

定义一个或多个XCTestException(通过调用XCTestCase的expectationWithDescription:方法获取XCTestExpection), 异步代码执行完成调用XCTestException实例的fullfill方法通知异步测试满足条件。然后再通过调用类中的waitForExceptionsWithTimeout:handler方法设置异步测试超时时间,并通过handler设置超时行为。

// 3.异步测试
- (void)testRequest {
    XCTestExpectation *requestExpectation = [self expectationWithDescription:@"send request"];

    AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];

    [mgr GET:@"https://baidu.com" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"responseObject:%@", responseObject);
        XCTAssertNotNil(responseObject, @"返回错误");
        [requestExpectation fulfill];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"error:%@", error);
        XCTAssertNil(error, @"请求出错");
        [requestExpectation fulfill];
    }];

    [self waitForExpectationsWithTimeout:3.0 handler:^(NSError * _Nullable error) {
        if (error) {
            NSLog(@"Timeout Error:%@", error.description);
        }
    }];
}

单元测试的意义

Luis Solano在Objc.io的一篇文章中《Bad Testing Practices 》总结了自动化测试的五个好处:
1. 使重构更为简单;
2. 避免代码恶化;
3. 提供可执行的说明和文档;
4. 减少创建软件的时间;
5. 减少创建软件的代价。
总的来说也可以通过Objc.io的另一篇文章《Real-World Testing with XCTest》中的一句话简述:
测试使我们的代码质量变的可靠,同时让我们重构或修改代码而不用担心修改是否破坏了其他部分。

参考资料

[官方文档–Writing Test Classes and Methods]
iOS 单元测试之XCTest详解(一)
ios UnitTest 学习笔记

你可能感兴趣的:(iOS录)