本地回归测试开始出现失败归属不清、UI 测试无法照搬,CI 结果也难以比较。
最快判断:不建议全量重写。新建的单元测试与直接调用业务代码的集成测试优先采用 Swift Testing;存量 XCTest 按维护频率渐进迁移;UI 自动化、性能测试及部分 Objective-C 异常测试继续保留 XCTest。
最后更新于 2026 年 9 月 2 日,版本与互操作信息核实自 Apple Developer 文档、WWDC26 视频、Xcode 27 Beta Release Notes 及 Swift Testing 官方仓库。
这篇文章适合三类人:维护大量 XCTest、担心一次性迁移破坏回归基线的存量 App 开发者;准备建立新测试体系的新项目开发者;以及需要在远程 Mac、Swift Package Manager 或持续集成环境中固定工具链的维护者。
00先按测试类型划分迁移边界
Swift Testing 与 XCTest 的选择,不应从“哪个框架更新”开始,而应从测试任务开始。Apple 当前给出的边界仍然是:Swift Testing 更适合单元测试和直接调用业务代码的集成测试,XCTest 继续覆盖 UI 自动化与性能测试。(测试框架官方说明)
| 测试类型 | 推荐策略 | 迁移优先级 | 不应忽略的验收证据 |
|---|---|---|---|
| 新建单元测试 | 优先 Swift Testing | 高 | 相同输入下的结果、错误与边界条件一致 |
| 直接调用业务代码的集成测试 | 优先 Swift Testing,必要时复用旧 Helper | 中高 | 依赖注入、异步流程和失败位置保持可诊断 |
| 存量 XCTest 单元测试 | 按修改频率增量迁移 | 中 | 缺陷仍能触发失败,跳过逻辑不改变 |
| UI 自动化 | 保留 XCTest | 低 | 页面驱动、控件定位、截图或交互结果 |
| 性能测试 | 保留 XCTest | 低 | 测量指标、测试计划配置和运行环境一致 |
| Objective-C 异常测试 | 继续使用 XCTest,必要时使用 Objective-C 测试 | 低 | 异常是否被正确捕获,而不是误判为进程崩溃 |
能不能把 XCTest 全部换成 Swift Testing?当前答案是否定的。Swift Testing 的定位是扩大 Swift 代码测试的表达能力,不是让所有界面驱动、性能测量和 Objective-C 异常测试都换成同一种写法;迁移资料也将小步迁移作为更稳妥的路径,而不是一次性修改全部旧测试。(WWDC26 测试迁移视频)
01新项目先建立 Swift Testing 单元测试基线
如果项目刚开始建立测试体系,单元测试不必再从 XCTestCase 继承。Swift Testing 使用 @Test 声明测试,#expect 表达预期,#require 用于失败后应立即终止当前测试的前置条件;这些写法对异步代码、参数化测试和并发执行更自然。(Testing 官方文档)
最小示例如下,项目名、Scheme 和路径均不包含真实业务信息:
import Testing
struct PriceCalculatorTests {
@Test(arguments: [0, 1, 10])
func rejectsInvalidQuantity(_ quantity: Int) {
#expect(quantity >= 0)
}
@Test
func createsOrder() throws {
let order = try #require(makeOrder())
#expect(order.isValid)
}
}
这里真正减少的是维护成本,而不是代码行数本身:
- 参数化测试可以把同一规则与多组输入绑定,避免手写大量重复测试函数;
#expect能保留表达式中的实际值,失败时比只看到断言文字更容易定位;#require把“没有这个前置条件就没有继续测试意义”的判断写得更清楚;- traits 和 tags 可以把测试按平台、功能、优先级或运行节奏筛选到不同的 Test Plan 中。
但新项目也不应为了“框架统一”删除 XCTest UI Tests Target。新项目可以让业务逻辑使用 Swift Testing,同时保留 XCTest UI Tests Target,界面测试仍由专门的 UI 测试入口执行。(Xcode 添加测试的官方说明)
停止条件:如果某个测试需要启动 App、查找界面控件、执行手势,或需要通过 XCTest 记录性能指标,就不要继续把它改写成 Swift Testing 单元测试。这不是迁移不彻底,而是测试能力与工具选择匹配。
02存量项目按维护频率渐进迁移
存量 XCTest 项目从哪里开始改,关键不在文件数量,而在测试未来还会被修改多少次。一次性重写大量稳定测试,通常会把可验证的业务变化变成难以审查的测试重构。
建议把存量测试分为三组:
- 正在修改的测试:如果某个测试正好覆盖新功能、修复缺陷或增加并发逻辑,优先在这次修改中迁移到 Swift Testing。
- 共享 Helper 较多的测试:先处理 Helper 中的断言与失败报告,再迁移调用它的测试,避免测试主体已经换了框架,但底层辅助方法仍然让失败信息丢失。
- 长期稳定且很少修改的测试:只要当前结果可靠、失败位置清楚,就可以暂时保留 XCTest,不必为了统计迁移比例而重写。
Swift Testing 与 XCTest 可以在同一测试 Bundle 中并行构建和运行,也可以在同一个文件中同时导入两个模块;但单个测试函数不应混用两套框架的生命周期与断言语义。(XCTest 迁移官方文档)
迁移共享 Helper 时,必须特别检查跨框架问题。当前迁移资料提供了 none、limited、complete 和 strict 等互操作模式;模式会影响一个框架中的测试调用另一个框架 API 时,失败究竟被忽略、警告、报告为错误,还是直接触发更严格的失败。具体行为应以当前 Xcode 版本的官方说明为准,不要把 Beta 阶段默认行为当作长期承诺。
迁移完成后,至少保留以下验收记录:
- 原来会失败的缺陷,在新测试中仍然失败;
- 原来的跳过、取消与条件启用逻辑没有变成“静默通过”;
- 失败位置能指向真正的 Helper 调用或测试断言,而不是只显示一个无关的测试入口;
- 迁移前后的 Test Plan 没有意外排除测试 Target、Suite 或参数化用例。
03UI、性能与 Objective-C 场景继续双轨运行
XCTest 为什么仍然需要保留?原因不是历史包袱,而是它还承担着不同类型的测试能力。
UI 自动化依赖 XCUIAutomation 来启动应用、定位控件并模拟用户操作;性能测试则依赖 XCTest 的测量 API 和测试计划配置;涉及 Objective-C 异常时,Swift 代码无法安全处理这类异常,因此相关测试仍应使用 XCTest,必要时使用 Objective-C 编写测试。
可以按下面的能力矩阵安排双轨:
- Swift Testing:纯 Swift 单元测试、并发业务逻辑、参数化输入、直接调用服务层或领域层的集成测试;
- XCTest:App 启动与界面操作、UI 回归流程、性能指标采集、需要既有 XCTest 生命周期的测试;
- 双轨 Helper:共享数据构造、测试夹具和业务断言,但要检查断言 API 是否能被当前互操作模式正确报告;
- 待复核项目:依赖特定 Xcode Beta 行为、特殊 Scheme 设置或未稳定的测试入口。
这也解释了为什么“把 UI 测试全部迁移掉”通常会造成回归覆盖下降。单元测试可以验证状态转换,却不能证明真实界面能启动、控件可定位、导航流程可完成;两者验证的是不同层次的问题。
04Swift Package 与 Apple App 项目分开判断
Swift Package、Apple 平台 App 和跨平台 Swift 项目,不能简单套用同一条迁移结论。
Swift Testing 官方仓库说明,它已随受支持的 Swift 工具链提供,并支持 Apple 平台、Linux 与 Windows;这意味着不依赖 Apple SDK、模拟器或 UI 的纯 Swift 测试,有机会在 Windows 或 Linux 上提前运行。(Swift Testing 官方仓库)
但以下测试仍然需要 macOS 与 Apple 工具链:
- 需要 Xcode Scheme、Test Plan 或
xcodebuild的 App 测试; - 需要 iOS 模拟器或真实 Apple 设备的集成验证;
- 需要 XCTest UI Tests 的界面自动化;
- 需要 Apple 平台 SDK、签名环境或 App 构建产物的测试。
swift test 与 Xcode Test Plan 也不能互相替代。Swift Package Manager 入口更适合验证包本身的跨平台逻辑;Xcode Test Plan 则可以控制测试 Target、配置、环境变量、代码覆盖率、模拟位置以及运行筛选。(Xcode 测试组织官方说明)
因此,跨平台项目可采用两层策略:先在非 macOS 环境运行纯 Swift 测试,再在 macOS 上运行 Apple 平台集成、UI 与打包相关测试。前者通过不代表后者一定可用,尤其不能把 swift test 的通过结果推广成 iOS App 全链路验证通过。
05远程 CI 固定入口后再提高互操作强度
两套测试框架在远程 CI 中如何对照结果,第一步不是直接把互操作模式切到最严格,而是固定测试入口,避免工具链、Scheme 和 Test Plan 同时变化。
可按以下 7 步执行:
- 锁定 Xcode 与 Swift 工具链:记录当前 Xcode 版本、Swift 版本、目标 SDK 和 macOS 版本。Xcode 27 目前仍应按 Beta 资料评估;其 Beta Release Notes 标明需要 Apple Silicon Mac,并要求 macOS Tahoe 26.4 或更高版本,不能把这些条件当成正式版长期承诺。(Xcode 27 Beta Release Notes)
- 固定 Scheme 与 Test Plan:不要只执行默认测试入口。为单元测试、集成测试和 UI 测试建立明确的测试计划,并在命令行显式指定。
- 记录迁移前基线:保存测试发现数量、通过与失败项、跳过项、失败路径和
.xcresult结果包。 - 先迁移一小组高频修改测试:优先选择业务逻辑测试,保留原有 UI Tests 与性能测试。
- 启用互操作检查:先观察
limited或complete模式暴露出的跨框架问题,处理共享 Helper 后,再考虑更严格的strict模式。不要为了“绿色构建”暂时使用none并把潜在断言问题隐藏起来。 - 重复同一 Test Plan:比较迁移前后的发现数量、失败归属、取消行为、日志和测试结果文件,而不只是比较最终退出码。
- 验证断线与重启恢复:远程 Mac 重启或会话中断后,仍应能重新选择同一 Scheme 和 Test Plan,运行 Swift Testing、XCTest 单元测试与 XCTest UI Tests,并留下可打开的结果产物。
使用 xcodebuild 执行测试时会生成 .xcresult 结果包,其中可包含会话结果、代码覆盖率和日志;该文件可以在 Xcode 中打开、分析或交给团队成员复核。(运行测试与解读结果的官方说明)
迁移决策可以直接按以下条件执行:
- 若是新项目,且测试主要直接调用 Swift 业务代码,则选 Swift Testing;UI Tests Target 继续使用 XCTest。
- 若是存量项目,且测试正在被频繁修改,则迁移当前修改范围;稳定测试先保留 XCTest。
- 若测试需要界面驱动或性能测量,则保留 XCTest,不因代码风格统一而改写。
- 若共享 Helper 同时被两套框架调用,则先验证互操作模式与失败归属,再扩大迁移范围。
- 若项目依赖
swift test跨平台运行,则先迁移纯 Swift 测试;Apple 平台集成验证回到 macOS 与 Xcode Test Plan。 - 若远程 CI 无法保存
.xcresult、无法固定 Scheme 或重启后丢失测试环境,则先修复 CI 可复现性,再推进框架迁移。
Xcode 27 仍处于 Beta 阶段,互操作默认行为、日志表现和部分命令行细节可能在 RC 或正式版阶段调整。发布前应再次核对迁移文档、Testing 文档、Xcode Release Notes 与 App Store Connect Release Notes,特别是互操作默认模式发生变化时,不要直接沿用旧流水线配置。
06给独立开发者的最终验收清单
在提交迁移 PR 或切换远程 CI 前,可以逐项勾选:
- ✅ 新增单元测试是否默认使用 Swift Testing?
- ✅ 直接调用业务代码的集成测试是否保留了原有测试语义?
- ✅ UI 自动化是否仍由 XCTest 与 XCUIAutomation 执行?
- ✅ 性能测试是否继续使用 XCTest 测量 API?
- ✅ Objective-C 异常场景是否避免用 Swift 测试错误捕获?
- ✅ 同一 Test Bundle 中两套框架是否都能被发现并执行?
- ✅ Test Plan、Scheme、环境变量与运行设备是否已固定?
- ✅ 迁移前后的失败、跳过和取消结果是否逐项对照?
- ✅
.xcresult是否能在远程任务结束后保存并下载? - ✅ 远程 Mac 重启后是否能重复运行同一套测试入口?
如果本地 Mac 无法长期运行双框架回归,问题通常不只是“缺一台编译机”:磁盘中的 Xcode、模拟器、缓存和结果产物需要持续维护,CI 还要处理登录会话、工具链一致性、远程连接中断与重启恢复。相比临时在 Windows 或 Linux 环境中拼接不完整的 Apple 测试链路,远程 Mac 更适合承担需要 Xcode、Test Plan、模拟器和 .xcresult 归档的持续验证任务。
如果只是偶尔验证一个 Swift Package,继续使用本地环境或跨平台机器更合适;如果需要持续运行 iOS 单元测试、UI Tests 和远程回归,NUKCLOUD 的 Mac 远程租赁方案可以作为按周期使用的测试环境。进一步规划区域时,可根据团队网络位置查看 美国远程 Mac 节点或 日本远程 Mac 节点,再用真实 Test Plan 验证连接、运行与结果留存是否满足项目要求。