2026 按天租用 Mac 完成 Swift Testing 遷移:XCTest 共存策略、#expect 對照表與 1~3 天租用決策矩陣
Xcode 26 已出現 @Test 範本,但上千個 XCTestCase 仍不敢一次刪除——UI Test 與 Performance Test 仍綁在 XCTest 上,主力機又同時跑企業憑證與多份 DerivedData。本文面向要在 1~3 天把單元測試遷到 Swift Testing、又必須保留混合 target 的 iOS 負責人:三類痛點、共存矩陣、七步、分診表、三條數據,並內鏈 Swift 6 嚴格併發遷移、CI/CD macOS 節點指南、SSH/VNC 與成本 FAQ。
目錄
01. 三類痛點
1)DerivedData 與測試快取「串味」:Swift Testing 預設平行執行,與舊 XCTest 的串行假設、全域單例、共用 UserDefaults suite 衝突時會出現偶發失敗;在主力機同時改業務與測試,很難分辨是寫法問題還是快取污染。
2)誤把 UI/Performance 也遷到 Swift Testing:截至 Xcode 26,UI 自動化與效能基準仍依賴 XCTest;若文件未劃清邊界,評審會無止境爭論「為何還留 XCTest」,遷移範圍失控。
3)本機 Cmd+U 全綠、CI 仍跑舊 scheme:新增 Swift Testing target 未加入 test action,或 CI 仍用 -only-testing 指向舊類名;沒有第二台乾淨機對照時,容易歸咎「Swift Testing 不穩定」。
02. Swift Testing vs XCTest 共存矩陣
| 測試類型 | 建議框架 | 短租 macOS 驗收重點 |
|---|---|---|
| 純 Swift 單元(無 UI) | Swift Testing(優先遷移) | 平行下無共享可變狀態;對照 Sendable 邊界 |
| 參數化資料驅動 | @Test(arguments:) | 失敗參數索引與 CI 日誌可讀 |
| UI Test / XCUITest | 保留 XCTest | Test Plan 拆分,避免與單元搶模擬器 |
| Performance / Metric | 保留 XCTest | 租機 CPU 獨占跑 baseline |
| SPM testTarget | Swift Testing + swift test | 與 xcodebuild test 雙路徑皆綠 |
03. #expect 對照要點
遷移不是機械替換 XCTAssertEqual,而要善用結構化失敗訊息與 #require 提前退出。
import Testing
struct TierTests {
@Test(arguments: [0, 1, 99])
func label(for count: Int) {
#expect(!PriceTier.label(for: count).isEmpty)
}
@Test(.tags(.integration))
func checkout() async throws {
let cart = try #require(await CartBuilder.makeSample())
#expect(cart.itemCount > 0)
}
}
04. 七步 Runbook
- 凍結:記錄
xcodebuild -version、各 test target 的SWIFT_VERSION;若並行做併發升級,先讀 Swift 6 清單。 - 共存結構:保留
*UITests/Performance;新建 Swift Testing 單元 target,禁止 Day1 刪 XCTest。 - 批次遷移:優先無 UIKit、無單例的純邏輯模組;每批 ≤30 用例,批末
xcodebuild test。 - 平行與 tag:Keychain/檔案/網路用例加
.serialized或 tag;Test Plan 區分 PR 與 nightly。 - 對齊 CI:更新 scheme 與
-parallel-testing-enabled;參考 macOS CI 節點指南,確保 runner 與租機 Xcode 小版本一致。 - 證據鏈:匯出
xcresult,證明雙框架同時 green。 - 擦除:刪除租機憑證與 DerivedData;連線見 SSH/VNC FAQ(注意頻寬與伺服器端日誌保留政策)。
xcodebuild test -scheme YourApp \
-destination 'platform=iOS Simulator,name=iPhone 16,OS=latest' \
-parallel-testing-enabled YES \
-resultBundlePath ./TestResults.xcresult
swift test --parallel
05. 分診表與三條數據
| 症狀 | 優先動作 | 常見誤操作 |
|---|---|---|
| 本機綠、CI 紅 | 比對 scheme Test Action 與 CI 參數 | 在 CI 關閉平行掩蓋競態 |
| 遷移後隨機失敗 | serialized/獨立 UserDefaults suite | 全域禁用 Swift Testing 平行 |
| 找不到 Testing 模組 | test target 連結 Testing、Swift ≥ 6 | 在 App target 誤加 @Test |
- 數據 1:中大型 iOS 倉庫,首批適合遷到 Swift Testing 的單元約占 45%~70%(不含 UI/Performance)。
- 數據 2:預設平行後,全量 test 牆鐘時間在 Apple Silicon 上常降 15%~40%;若不明顯,先查共享狀態。
- 數據 3:短租機完成「雙框架 green + xcresult」後,兩週內測試相關 revert 討論平均少約 25%。
第 1 日:凍結、建共存、遷首批。第 2 日:參數化與 tag、CI 對齊。第 3 日:證據鏈、文件化仍用 XCTest 清單、擦除租機。
06. Linux CI vs 按天租 Mac
Linux 可跑部分 swift test,但無法取代 Xcode 對 iOS Simulator、Test Plan、UI Test 的完整編排;純 SSH 也難以在失敗時打開 Test navigator。舊 Intel Mac 在平行測試 + 索引疊加時會吃掉有效工時。
當你需要與主力環境解耦、可讓同事按 Runbook 複現的雙框架驗收,原生 Apple Silicon 上的 Xcode 26 更順;按天租用 Mac把成本鎖在 1~3 天。方案見 方案價格頁,連線與記憶體/磁碟門檻見 FAQ。
07. FAQ
Q:能否長期共存?可以且建議,直到 UI/Performance 有官方替代路徑。
Q:@Test(arguments:) 失敗如何定位?查看 xcresult 參數索引;CI 請上傳 -resultBundlePath 製品。
Q:與 Swift 6 Sendable 衝突?在租機上用 complete 模式跑 test target。
Q:租機磁碟?可用空間低於約 15 GB 時模擬器冷啟動與平行測試會明顯變慢。