測試與程式碼品質

Swift Testing:取代 XCTest 的 Apple 新標準(快速整理)

在進行 iOS 開發、撰寫測試程式碼時,總會有開始對 XCTest 感到有些受限的時候。

閱讀 4 分鐘
Swift Testing:取代 XCTest 的 Apple 新標準(快速整理) 封面圖

在進行 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 等多種 API 統一使用 #expect
失敗訊息 不易看見值 自動顯示實際值
重複測試 手動撰寫 for 迴圈 預設支援參數化測試
平行執行 有限 預設平行執行

最讓我驚豔的是參數化測試。

需要只改變值、重複驗證相同邏輯時,以前得跑 for 迴圈或複製貼上函式。

在 Swift Testing 中,只要將引數列表傳給 @Test,就會自動逐一執行。

它也會精確指出失敗案例使用的是哪些值。

現在就能使用嗎?

可以。如果是新專案,我建議現在就導入。

在 Xcode 16 以上、Swift 6 的環境中,幾乎不需要特別設定。

不過有一點需要知道:Swift Testing 和 XCTest 可以在同一個專案中共存。

也就是說,不必一夜之間重寫所有既有的 XCTest 程式碼。

新撰寫的測試使用 Swift Testing,既有測試再慢慢移植即可。

從新的測試開始逐一移植就足夠了
從新的測試開始逐一移植就足夠了

有一點要注意的是 UI 測試。會自動操作畫面的 XCUITest 系列,目前仍屬於 XCTest 的範圍。

因此,短期內以 Swift Testing 處理單元測試、以 XCTest 處理 UI 測試,是比較務實的組合。


移植時值得知道的事項

以下分享幾個我在實際移植過程中覺得有用的技巧。

首先,使用 init 和 deinit 取代 setUp、tearDown。因為 Swift Testing 會為每個測試建立新的實例。

因此能大幅減少測試之間狀態意外混用的錯誤。

如果某個值一定要存在才能進入下一步,請使用 #require,而不是 #expect。

條件不符合時,#require 會立即停止測試。

看到綠燈後,@Test 會讓人不知不覺上癮
看到綠燈後,@Test 會讓人不知不覺上癮

標籤(Tag)功能也很實用,可以將相關測試分組,一次執行或篩選。

要確認錯誤是否正確拋出時,可以使用 #expect(throws:)。

總結

Swift Testing 已不是剛推出的實驗功能,而是 Apple 正積極推動的下一個標準。

不必立刻全部改掉,但從新的測試開始逐一使用,很快就會習慣它的便利。

如果你曾對 iOS 測試程式碼感到受限,今天不妨先將一個測試移植成 @Test。

延伸閱讀