Xcode 27 中,Swift Testing 测试调用 XCTest 断言后,CI 结果和本地不一致,或旧测试计划仍显示警告。
最快判断:增量迁移先用 complete 评估;它保留跨框架问题原有严重级别。先检查旧 Test Plan,因为较早创建的计划可能仍是 limited。strict 适合要阻止特定 XCTest 调用的团队;不要把 none 当作让 CI 变绿的常规修复。 (Apple 迁移文档)
维护 XCTest 存量、准备逐步引入 Swift Testing 的开发者,可据此选迁移模式。
负责 Xcode Test Plan 和 CI 的工程师,可用本文核对执行设置是否一致。
制定测试规范的技术负责人,可据此区分兼容迁移、严格治理和临时排障。
01 先确认互操作解决的是跨框架问题
Swift Testing 与 XCTest 可以共存在同一个测试目标中;同一源文件也可以同时导入两个框架。互操作设置不会把一个框架替换成另一个,它决定的是:测试从一个框架运行、却调用另一个框架的断言或问题记录 API 时,测试运行器如何处理这类跨框架问题。Apple 的迁移文档说明了混合测试与共享测试辅助函数的用法。
最小例子是 Swift Testing 测试调用 XCTFail:
import Testing
import XCTest
@Test func sharedHelperReportsFailure() {
XCTFail("检查跨框架问题是否被记录")
}
它用于检查互操作行为,不代表你应该在新测试里继续依赖 XCTest 断言。迁移后可以把共享辅助函数改为 Swift Testing API;例如 Issue.record 可记录问题,相关接口见 Apple 的 Issue.record 文档。
两套框架也不是完全可互换。Apple 将 Swift Testing 定位为新的测试框架,同时继续提供 XCTest;UI 自动化仍与 XCTest 的 XCUIAutomation 工作流相关。先按测试类型决定保留什么,再决定互操作模式,避免把“迁移单元测试”误当作“必须一次替换整个测试体系”。Xcode 测试概览与 XCTest 框架说明列出了各自的适用范围。
02 用问题严重级别选模式
Xcode 27 的互操作模式有 limited、complete、strict 和 none。选型关键不是名字,而是跨框架调用出现后,失败是否保留、是否出现迁移提示,以及测试是否会被中止。Apple 的迁移文档与 WWDC26 迁移演示说明了模式差异。
limited:保留兼容性提示。 Swift Testing 侧的问题维持原有严重级别;XCTest 侧的问题以警告呈现,并附带现代化提示。适合先发现问题、暂不改变旧测试失败策略的阶段。complete:渐进迁移的评估起点。 两个方向的跨框架问题都维持原有严重级别,并提供迁移提示。若 XCTest 断言本来会使测试失败,问题不应仅因它被 Swift Testing 测试调用就降为警告。strict:阻止特定调用。 Swift Testing 侧的问题仍维持原有严重级别;Swift Testing 测试调用 XCTest API 时,相关问题会以fatalError()处理。适合团队已明确要求禁止这类调用、并准备修复触发点的情况。none:关闭互操作处理。 跨框架问题不会被报告。只有在定位配置故障等明确排障目的下短暂使用;否则可能把有价值的失败一起隐藏。
limited 和 complete 应该怎么取舍?
如果你要逐步迁移,又不希望 XCTest 断言失败被降成警告,先在测试计划中选 complete,跑过混合测试后再决定是否继续收紧。若团队只想先看见迁移提示、还不能接受失败行为变化,可以保留 limited,但要记录哪些警告尚未处理。
03 旧 Test Plan 不能按 Xcode 版本猜默认值
Xcode 27 的新项目使用 complete;较早创建的 Test Plan 可能沿用 limited。因此,升级 Xcode 后看到 limited 并不必然是升级失败,也不能只看当前 Xcode 版本推断测试计划的实际模式。WWDC26 演示明确展示了新旧计划的差别,并指出设置位于 Test Plan 的测试执行区域。
在 Xcode 中打开当前 scheme 实际使用的 Test Plan,进入 Test Execution 区域,核对 Swift Testing and XCTest Interoperability 的选项。不要只检查项目里某个 .xctestplan 文件:同一个 scheme 可能关联不同计划,命令行也可以指定具体计划。Apple 的测试计划配置说明介绍了计划与 scheme 的关系;命令行运行测试说明列出了从命令行选择计划的方式。
为什么旧计划升级后还是 limited?
因为项目创建时间和计划自身设置会影响实际行为。打开当前启用的计划确认配置;若 CI 用 xcodebuild 指定了另一份计划,也要检查那份文件,而不是仅修改 Xcode 中当前展示的计划。
04 Swift Package 的默认值要连工具链一起看
Swift Package 与 Xcode 项目不能只凭“都在 Xcode 27 里运行”就假定默认模式相同。Apple 的迁移文档把 Swift Package 的默认值与 Swift 工具链版本、包的 swift-tools-version 一起说明:工具链低于 Swift 6.4 时,默认是 none;工具链达到 Swift 6.4、而包声明低于 Swift 6.4 时,默认是 limited;两者都达到 Swift 6.4 时,默认是 complete。这描述的是文档所列的 Swift Package 默认行为,不是所有 Xcode Test Plan 的通用默认值。
如果要明确覆盖 Swift Package 的默认模式,可在运行测试前设置 SWIFT_TESTING_XCTEST_INTEROP_MODE 环境变量,值使用模式名。先确认命令行测试进程实际继承了该变量;仅在 shell 配置里写入,不等于 CI 作业一定收到它。模式定义与变量名以 Apple 迁移文档为准。
Swift Package 和 Xcode 项目的默认模式是否相同?
不能直接认为相同。Swift Package 的默认行为受工具链与 swift-tools-version 影响;Xcode 项目还要检查实际使用的 Test Plan。对照运行前,分别记录包声明、执行工具链与计划设置。
05 用同一组跨框架测试验收本地与 CI
验证设置时,不要先改完整测试套件。准备一个可重复的最小样例:一条 Swift Testing 测试调用 XCTest 断言,再加一条 XCTest 测试记录 Swift Testing 问题。保存运行日志或测试结果,确认问题有没有被记录、严重级别是否符合预期、旧测试是否仍然运行。
按这份清单执行,发现差异时先定位测试入口,不要立即关闭互操作:
- [ ] 在当前 Xcode scheme 中确认默认 Test Plan,并记录互操作模式。
- [ ] 检查命令行是否指定了其他 Test Plan;核对 Xcode 与
xcodebuild的计划选择。 - [ ] 对 Swift Package 记录 Swift 工具链版本与
swift-tools-version,不要把包的默认值套用到 Xcode 项目。 - [ ] 用同一最小样例分别运行 Swift Testing 调用 XCTest API、以及 XCTest 调用 Swift Testing API 的情形。
- [ ] 对比本地 Xcode、命令行和远程 CI 的输出:问题是否出现、是否失败、是否有迁移提示。
- [ ] 如果结果不一致,检查环境变量、scheme、计划文件和 CI 实际执行命令;修正后重跑样例与原有混合测试套件。
- [ ] 将选定模式及预期结果写入团队测试规范,避免后续工具链更新后靠猜测排障。
Apple 的 Xcode 27 发布说明确认了互操作设置,并记载相关测试问题的处理;实际验收仍应以你当前项目的运行结果为准。不要把 WWDC 演示中的示例输出当成本地或本站实测。
若你在 Windows 或 Linux 工作站上发起构建,远程 Mac CI 还要额外核对执行节点上的 Xcode、测试计划与 Swift Package 工具链;本地通过并不能证明远程节点使用了相同配置。需要配置 macOS 测试环境时,可先查看 CALMVPS 的远程 Mac 开发与测试入口,再按实际项目复核执行命令与结果证据。
06 先核对计划,再决定是否迁移
增量迁移时,先选 complete 做评估;如果旧 Test Plan 实际仍是 limited,先弄清楚它与当前运行入口的关系,再决定是否改动。用同一测试样例比较本地与 CI,按问题可见性、严重级别和旧测试兼容性验收;只有明确要阻止 XCTest API 调用时,才将 strict 作为治理策略。
如果你暂时没有可运行 Xcode 测试的 Mac 环境,Windows 或 Linux 可以继续承担编辑、提交和任务触发,但无法取代 macOS 测试工具链;自购 Mac 更适合长期、稳定使用且需要本地设备接口的场景。临时增加构建或迁移验证环境时,CALMVPS 提供按周期租用远程 Mac 的选择,你可以先查看远程 Mac 套餐与租赁周期,再判断它是否适合当前测试任务。