测试类型
- 单元测试:模拟环境下测试一个独立方法来保证其有效性
- 功能测试:在真实环境下测试一个方法来确保准确性
- 性能测试:测试一个方法、模块或完整应用的性能
定义
- 测试用例:需要进行测试的一个场景,包含一个方法、功能或程序执行所需的条件,需要一系列输入变量,以及一个期望行为
- 测试夹具:进行一个或多个测试用例前所需的准备和清理阶段,包括对象创建、依赖项设置、数据库设置
- 测试套件:包含一系列测试夹具的测试用例,可以嵌套其他套件,聚合应当一起执行的测试用例
- 测试运行器:执行测试并提供结果的系统,如 Xcode 就是一个图形化的测试运行期
- 测试报告
- 测试覆盖率:衡量测试套件进行的测试数量,并可以发现应用未被测试的部分
- 测试驱动开发
单元测试
Xcode 内置 XCTest 作为单元测试框架。
设置 XCTest
File -> New -> Target -> iOS Unit Testing Bundle
编写单元测试
XCTest 的一个测试夹具类必须继承自 XCTestCase,这个类大致包括以下方法
- +[setUp] 在调用所有测试方法之前调用,用于初始化
- -[setUp] 在调用某个测试方法之前被调用
- [testXXX] 具体的测试用例方法
- -[tearDown] 单个测试用例方法清理方法
- +[tearDown] 测试夹具清理方法
一个简单的单元测试
- (void)testExample {
XCTAssertTrue(1 < 2);
}
- (void)testFailExample {
XCTAssertTrue(1 < 2);
}
一个异步的单元测试
- (void)testAsyncTask{
XCTestExpectation *expectation = [self expectationWithDescription:@"Test Async Task"];
dispatch_async(dispatch_get_main_queue(), ^{
XCTAssertTrue(1 < 2);
[expectation fulfill];
});
[self waitForExpectationsWithTimeout:1 handler:^(NSError * _Nullable error) {
NSLog(@"waitForExpectationsWithTimeout 超时!超时!超时!");
}];
}
这里要注意,waitForExpectationsWithTimeout 方法用于在指定时间后检测测试用例结果,fulfill 表明测试用例已经结束,如果 waitForExpectationsWithTimeout 检测时测试用例没有结束则会调用 handler 中的闭包。
一个性能单元测试
- (void)testPerformanceExample {
[self measureBlock:^{
for(NSInteger i = 1; i < 1000; i++) {
for (NSInteger j = 1; j < i; j++) {
NSInteger k = j * i;
}
XCTAssertTrue(1 < 2);
}
}];
}
它会对闭包中的方法进行十次运行并统计运行时间的平均值和标准差。
模拟依赖
单元测试关注主要测试对象的功能和行为,对于涉及到的其他次要对象尤其是依赖关系的对象,仅仅关注其交互以及返回的结果和发生的异常,因此需要模拟一些依赖关系。
测试替身 Test Double
- dummy:仅仅用来通过编译,实际并不使用和考虑其实现
- fake:对于耦合的组件有简单的实现,使用时先对替换的全局对象和类进行备份,测试完成后恢复
- stub:对于依赖对象有显式的类实现,但不关注其调用,方便复用,但是不能从测试代码直接获取其实现细节
- spy:与 stub 类似,但是能捕获参数和状态信息,记录调用方法
- mock:最普遍和常用,利用工具包隐式实现对象,关注交互和结果期望
测试及组件设计
测试和测试框架都可能影响到组件的设计,解决方案有
- 使用模拟数据或方法替换,但是需要深入了解组件,随着方法增多,测试会变得臃肿和难以管理
- 使用可配置组件,利用可重置的组件或依赖注入的生成器模式
持续集成与自动化
迭代开发流程图一个典型的开发迭代过程,涉及开发人员编写代码,然后提交到一个 VCS,触发构建管道,进行所有测试,代码分析,构建出二进制包用于手动测试,然后进行签名发布。
最佳实践
- 测试所有代码,包括初始化方法
- 测试参数值所有组合
- 不测试私有方法
- 消除外部依赖
- 每个测试运行前设置状态,运行后清理状态
- 测试用例应当可重复
- 测试用例必须使用断言来验证是否通过
- 应当启用代码覆盖率报告
网友评论