第一章:iOS测试概览
为什么需要自动化测试?
说实话,我刚入行那会儿,对测试这事也不太在意。总觉得「代码能跑就行,测什么测」。直到有一次,我负责的一个电商App在上线前夜,发现购物车结算金额总是多出几毛钱。排查了整整6个小时,最后发现是某个工具类里浮点数精度处理出了问题。
你想想看,这种问题如果靠人工去测,得点多少次「加入购物车」才能发现?而且每次发版都要重复测一遍,谁受得了?
自动化测试的核心价值,我总结下来就三点:
- 回归保障:改了一个地方,不用担心炸了别的地方
- 效率提升:机器跑一遍测试,比你手动点半小时快得多
- 质量门禁:测试不通过,代码就不让合入,从源头卡住问题
我的经验:在一个中型项目中,我们团队从零开始搭建自动化测试体系。刚开始大家觉得「浪费时间」,但三个月后,线上Bug率下降了约60%。嗯,数据不会骗人。
单元测试 vs UI测试:到底有什么区别?
很多新手会混淆这两个概念。我简单说下我的理解。
单元测试,说白了就是测「最小单元」。比如一个函数、一个方法、一个类。它不依赖UI,不依赖网络,甚至不依赖数据库。跑起来飞快,毫秒级出结果。
UI测试,则是模拟用户操作。点按钮、滑动列表、输入文字、验证界面变化。它跑得慢,但能发现集成层面的问题。
| 对比维度 | 单元测试 | UI测试 |
|---|---|---|
| 测试粒度 | 函数/方法级别 | 用户操作级别 |
| 执行速度 | 毫秒级 | 秒级甚至分钟级 |
| 依赖环境 | 无依赖或Mock | 需要真机或模拟器 |
| 发现问题类型 | 逻辑错误、边界条件 | UI布局、交互流程 |
| 维护成本 | 低 | 较高(UI易变) |
我的建议:单元测试和UI测试不是二选一,而是互补关系。我习惯用「测试金字塔」来规划:底层大量单元测试,中间少量集成测试,顶层极少量UI测试。这样既快又稳。
Xcode测试框架介绍:XCTest
XCTest是苹果官方提供的测试框架,从Xcode 5开始就内置了。你不需要额外安装任何东西,新建项目时勾选「Include Tests」就能用。
它的核心就几个东西:
- XCTestCase:测试用例的基类,你写的所有测试方法都继承它
- XCTAssert:断言家族,用来验证结果是否符合预期
- setUp / tearDown:每个测试方法执行前后的钩子,用来准备和清理环境
来看一个最简单的例子:
import XCTest
@testable import MyApp
class CalculatorTests: XCTestCase {
var calculator: Calculator!
override func setUp() {
super.setUp()
calculator = Calculator()
}
override func tearDown() {
calculator = nil
super.tearDown()
}
func testAddition() {
let result = calculator.add(2, 3)
XCTAssertEqual(result, 5, "2 + 3 应该等于 5")
}
func testDivisionByZero() {
let result = calculator.divide(10, 0)
XCTAssertNil(result, "除以0应该返回nil")
}
}
我曾经踩过的坑:在setUp里创建对象,但忘了在tearDown里释放。结果多个测试用例之间共享了状态,导致测试结果不稳定。记住:每个测试方法应该是独立的,互不干扰。
XCTest还支持性能测试、异步测试、UI测试等高级功能。后面章节我们会逐一深入。
测试的命名规范
我个人习惯用这种命名方式:
- test + 方法名 + 场景 + 预期结果
- 例如:
testAddWithPositiveNumbers_ReturnsCorrectSum - 例如:
testLoginWithInvalidPassword_ShowsErrorMessage
这样命名的好处是:测试失败时,从名字就能大概猜到是什么场景出了问题,不用点进去看代码。
什么时候不该写测试?
嗯,这个问题可能有点反直觉。但确实有些场景不适合写自动化测试:
- 原型验证阶段:UI和逻辑频繁变动,测试维护成本太高
- 一次性脚本:用完就扔的代码,没必要写测试
- 第三方SDK的封装:如果只是简单调用,测试价值不大
但话说回来,核心业务逻辑、公共工具类、网络请求层,这些是必须覆盖的。我在项目中见过太多「不敢改代码」的情况,就是因为没有测试兜底。
一句话总结:自动化测试不是银弹,但它能让你在深夜改代码时,睡得踏实一点。
下一章,我们会深入XCTest的具体用法,包括断言家族、测试生命周期、以及如何组织测试文件。敬请期待。