在做 iOS 端的单元测试时,XCode 自身集成的 XCTest 框架是一个不错的选择。网络上关于 XCTest 单元测试的文章不胜枚举,这里主要结合实例和 WWDC2018 的新增特性进行总结和梳理。
本文只针对 iOS 单元测试,UI自动化测试会在以后的博文中陆续展开,下面直接从 Demo 入手。
在创建好工程后(勾选上"Include Unit Tests"),会在 XCTests.m 中发现一些共同的方法:
- (void)setUp {
} // 将要执行测试代码时调用
- (void)tearDown {
} // 测试代码执行完后调用,测试失败不调用
- (void)testExample {
} // 单元测试用例执行主体
- (void)testPerformanceExample {
} // 性能测试用例执行主体
值得注意的是,单元测试类类名都以 Tests 结尾,同一类中的所有测试方法都以 -(void)test 开头。
在控制器 ViewController.m 中定义了字符串的 md5 加密算法,代码如下所示。现在要测试该方法的正确性,则需要依照以下步骤:
(1)前置条件构建(包括形参构建以及部分属性初始化等操作);
(2)在 - (void)testExample {} 方法中调用待测试方法(此处即为 string2md5 方法);
(3)使用 XCTAssert 断言检验方法正确性。
- (NSString *)string2md5:(NSString *)inputString {
const char *cStr = [inputString UTF8String];
unsigned char result[16];
CC_MD5(cStr, (CC_LONG)strlen(cStr), result);
return [NSString stringWithFormat:
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
result[0], result[1], result[2], result[3],
result[4], result[5], result[6], result[7],
result[8], result[9], result[10], result[11],
result[12], result[13], result[14], result[15]
];
}
单元测试用例方法详情及程序执行结果如下图所示,可以看出,通过 XCTAssert 断言确定了 md5 算法执行结果在字符串长度方面的有效性,单元测试代码执行完毕后也成功调用了 - (void)tearDown {} 方法。
同样地,在控制器 ViewController.m 中定义了累加函数,代码如下所示。可在 XCTests.m 中实现性能测试方法方法执行性能进行评估,具体性能参数在此不赘述。
- (void)performanceExample:(NSInteger)number {
NSInteger index = 0;
for (NSInteger i = 0; i <= number; i ++) {
index += i;
}
}
为便于理解并形成完整的工程化概念,此处给出完整的示例代码工程链接:XCTest-Demo。
在 WWDC2018 中,苹果在 iOS 单元测试方面做了一些细节方面的优化和改变,此处对其中三点进行简要总结:
(1)Code Coverage:在 WWDC2018 中,苹果重写了 Code Coverage (代码覆盖率)功能,优化了其性能和准确率,苹果内部的一项大型项目的数据显示,代码覆盖率功能性能提升了95%,且代码覆盖文件的大小也降低到了较低的水平,同时准确度也比以前有了不小的提升。并且,还推出了一个全新的命令行工具 xccov,关于该工具的使用等细节会在之后的博文中详细介绍;
(2)部分用例测试:在 Xcode10 中,可以选择 scheme 是否自动包含新添加的测试用例,如下图所示,避免每次都执行不必要的测试,达到只执行部分测试的效果;
(3)指定测试顺序:Xcode10 以前,测试顺序默认是按照用例函数名称进行排序的,这种排序形式的弊端是对于一些具有特定顺序依赖的测试用例而言,可能会导致测试失败。为此,在写测试用例时,应保持测试的独立性,不在不同测试间共享状态,Xcode10 提供了随机测试顺序模式以防止这种潜在的依赖关系,如下图所示: