Swift Testing Traitの使い方

に公開

概要

Swift 6.1 の Swift Testing では、Trait を テストスイート(構造体)全体に適用できるようになりました。

本記事では「ログ出力を共通化する」というシンプルなケースで、TestScoping を使った Trait の suite 適用を解説します。

やりたいこと

Swift 6.1で導入されたSuiteに Trait を適用して共通の前後処理をまとめます。
すべてのテスト関数の前後でログを出します

🟢 Start test...
(テスト処理)
🔴 End test...

Trait の定義

import Testing

struct LoggingTrait: SuiteTrait, TestScoping {
  var isRecursive: Bool { false } // suite 全体に一度だけ適用される

  func provideScope(
    for test: Test,
    testCase: Test.Case?,
    performing function: @Sendable () async throws -> Void
  ) async throws {
    print("🟢 Start suite: \(test.name)")
    defer { print("🔴 End suite: \(test.name)") }
    try await function()
  }
}

extension Trait where Self == LoggingTrait {
  static var logSuite: Self { Self() }
}
  • isRecursive = false により、suite 全体で 1 回だけ実行されます。
  • provideScope 内で function() を呼ぶ前後にログ出力。

テストコード(Suite に Trait を適用)

@Suite(.logSuite)
struct MyTests {
  @Test
  func testOne() throws {
    print("✅ testOne executed")
  }

  @Test
  func testTwo() throws {
    print("✅ testTwo executed")
  }
}

実行結果

🟢 Start suite: MyTests
✅ testOne executed
✅ testTwo executed
🔴 End suite: MyTests

Point

  • Trait を suite に適用することで、全テスト共通の処理を一箇所にまとめられる
  • 各テストがすっきりし、読みやすく・書きやすくなる
  • TestScoping を使えば、開始前と終了後の処理を安全に挟み込める

isRecursiveの使い分け

適用範囲 向いている用途例
false(非再帰) suite全体で1回 DB接続やモックの起動など重い処理
true(再帰) 各テスト関数ごと 毎テストで状態を初期化したいとき、ロギングなど軽量な処理

まとめ

機能 説明
SuiteTrait テストスイート(構造体)に適用できる Trait
TestScoping 前後処理(スコープ)を追加するプロトコル
provideScope(...) テスト実行を包み込むスコープ関数

応用編

下記のような用途にも利用が可能そうです

  • DB接続の初期化&クリーンアップ
  • サーバーのモック起動/停止
  • テスト環境の一括セットアップ

関連リンク

GitHubで編集を提案

Discussion