在进行 iOS 开发、编写测试代码时,总会有开始觉得 XCTest 有些受限的时刻。
我也有同感:以 func test 开头的函数名、XCTAssertEqual 这类冗长的断言,以及失败时无法一眼看出问题的消息。
就在这时,Apple 在 WWDC 2024 上发布了名为 Swift Testing 的新框架。
先说结论,Swift Testing 确实是 Apple 官方推出、用于取代 XCTest 的新标准。只需使用 @Test 宏和一个 #expect,就能编写简洁得多的测试,而且从 Xcode 16 起已内置。
本文将结合我的实际使用经验,整理 Swift Testing 是什么、与 XCTest 有何不同,以及现在是否可以立即使用。
什么是 Swift Testing?
Swift Testing 是 Apple 在 WWDC 2024 上公开的开源测试框架。
它充分利用了 Swift 的最新功能之一:宏。
最大的区别在于,XCTest 源自 Objective-C 时代,而 Swift Testing 从一开始就按照 Swift 的风格设计。
从 Xcode 16 起无需单独安装即可使用,Swift 软件包中也能直接使用。
最明显的变化是语法。测试函数名不再需要以 test 开头。
只需在函数上方添加 @Test,它就会成为一个测试。
import Testing
@Test func 检查_购物车_总价是否正确() {
let cart = Cart(items: [1000, 2000])
#expect(cart.total == 3000) // 失败时显示实际值
}
如上面的代码所示,只需在 #expect 中直接放入普通的比较表达式即可,无需记住 XCTAssertEqual 和 XCTAssertTrue。
它与 XCTest 有什么不同?
我把亲自迁移代码时感受到的主要区别整理成了表格。(截至 2026 年)
| 项目 | XCTest | Swift Testing |
|---|---|---|
| 测试声明 | 以 func test 开头 | @Test 宏 |
| 断言 | 多个,如 XCTAssertEqual | 统一使用 #expect |
| 失败消息 | 不易看清值 | 自动显示实际值 |
| 重复测试 | 手动编写 for 循环 | 默认支持参数化测试 |
| 并行执行 | 有限 | 默认并行执行 |
最让我惊喜的是参数化测试。
需要只改变值、重复验证相同逻辑时,以前要运行 for 循环或复制粘贴函数。
在 Swift Testing 中,只需向 @Test 传入参数列表,它就会自动逐个执行。
它还会准确指出失败用例对应的值。
现在就可以使用吗?
可以。如果是新项目,我建议现在就采用。
在 Xcode 16 或更高版本、Swift 6 环境下,几乎不需要进行额外配置。
不过有一点需要了解:Swift Testing 和 XCTest 可以在同一个项目中共存。
也就是说,不必一夜之间重写所有现有的 XCTest 代码。
新编写的测试使用 Swift Testing,现有测试慢慢迁移即可。
需要注意的一点是 UI 测试。自动操作屏幕的 XCUITest 系列目前仍属于 XCTest 的范围。
因此,暂时采用单元测试使用 Swift Testing、UI 测试使用 XCTest 的组合更为实际。
迁移时值得了解的事项
下面介绍几个我在实际迁移过程中觉得有用的技巧。
首先,用 init 和 deinit 代替 setUp 和 tearDown。因为 Swift Testing 会为每个测试创建新实例。
这样可以大幅减少测试之间意外共享状态的问题。
当某个值必须存在才能进入下一步时,使用 #require,而不是 #expect。
如果条件不满足,#require 会立即停止测试。
标签(Tag)功能也很实用,可以将相关测试分组后一次运行或筛选。
要确认错误是否正确抛出,可以使用 #expect(throws:)。
总结
Swift Testing 已不再是刚出现的实验功能,而是 Apple 正在推动的下一个标准。
不必马上改变所有内容,但从新测试开始逐个使用,很快就会习惯它的便利。
如果你曾对 iOS 测试代码感到受限,今天不妨先把一个测试迁移到 @Test。

