874 Views
June 04, 25
スライド概要
関西モバイルアプリ研究会A #8 - connpass
https://kanmoba.connpass.com/event/355831/
#関モバ で Swift Testing のアップデートについて話しました - usami-kの日記
https://usami-k.hatenablog.com/entry/2025/06/05/080709
https://usami-k.github.io/
Swift Testing のアップデート 宇佐見公輔 2025-06-04 / 関西モバイルアプリ研究会 A #8 株式会社ゆめみ
自己紹介 宇佐見公輔(うさみこうすけ) • 株式会社ゆめみ:iOS テックリード 近況 • 技術書典 18 で新刊を出しました • 紙+電子版を頒布(〜6/15(日)) 1 / 26
宣伝 ゆめみ大技林 • 今回で 6 冊目 • 参加著者数もページ数も過去最大 • 無償頒布 僕が書いた記事 • Rust Bevy によるクリエイティブ コーディング 2 / 26
Swift Testing とは
概要 • Swift でのユニットテストの新しいフレームワーク • Swift 6.0 / Xcode 16.0 に統合(2024 年 9 月) 主な特徴 • マクロ機能を活用したテスト記述 • パラメトライズテスト • テストの並列実行 • XCTest と併用可能 Swift Testing とは 4 / 26
テストコードの例 @Test func addBookSuccessfully() { let library = MySimpleLibrary() let book = MySimpleBook(isbn: "1234567890123") library.addBook(book) #expect(library.count == 1) #expect(library .findBook(byISBN: "1234567890123") != nil) } Swift Testing とは 5 / 26
アップデート • Swift 6.1 / Xcode 16.3 で機能更新(2025 年 3 月) • Swift Testing 本を出すとき、更新内容もいくつか反映 今回の話 Swift 6.1 / Xcode 16.3 での更新内容をいくつか紹介します。 Swift Testing とは 6 / 26
UI テストのフレームワーク が独立
XCUIAutomation • Swift Testing を使う場合も、UI テストは XCTest で書く import XCTest • UI テストの機能が、XCTest から分離された • それが XCUIAutomation フレームワーク import XCUIAutomation • 余談:“XC”という接頭語がやや冗長な気もする UI テストのフレームワークが独立 8 / 26
エラーのテストの改善
エラーのテストの基本 • #expect(throws:) や #require(throws:) を使う • これは従来も更新後も同じ #expect(throws: MyError.self) { try myModel.doSomethingError() } エラーのテストの改善 10 / 26
エラーのテストのカスタマイズ:従来(deprecated) • エラーのチェックをカスタマイズしたい場合は、次の形のマクロを 使って throws 引数のクロージャの中に判定を書いていた #expect { try myModel.doSomethingError() } throws: { error in let myError = try #require(error as? MyError) return myError.code == .error1 } エラーのテストの改善 11 / 26
エラーのテストのカスタマイズ:更新後 • #expect(throws:) や #require(throws:) がエラーを return するようになった • シンプルなテストコードで書ける let error = try #require(throws: MyError.self) { try myModel.doSomethingError() } #expect(error.code == .error1) エラーのテストの改善 12 / 26
パラメトライズテストの型 推論
パラメトライズテストの基本 @Test(arguments: [ ( book: MySimpleBook(isbn: "1234567890123"), searchISBN: "1234567890123" ) ]) func addBook(book: MySimpleBook, searchISBN: String) { // ... } パラメトライズテストの型推論 14 / 26
型推論の制約:従来 • arguments の箇所はテスト関数からは型推論されないので、明 示的な型指定が必要だった @Test(arguments: [ ( book: Optional<MySimpleBook>.none ) ]) func addBook(book: MySimpleBook?) { // ... } パラメトライズテストの型推論 15 / 26
型推論の拡張:更新後 • arguments の箇所も型推論されるようになった @Test(arguments: [ ( book: nil ) ]) func addBook(book: MySimpleBook?) { // ... } パラメトライズテストの型推論 16 / 26
非同期処理のテストの改善
非同期処理のテストの基本 • そもそもの基本は Swift Concurrency を使うこと • それで難しい場合に confirmation を使う await confirmation { confirm in library.eventHandler = { _ in confirm() } await library.addBook(book) } 非同期処理のテストの改善 18 / 26
カウントが追加 • confirm の回数をテストできるように • 0 を指定すると「呼ばれないこと」をテストできる await confirmation(expectedCount: 1) { confirm in library.eventHandler = { _ in confirm() } await library.addBook(book) } 非同期処理のテストの改善 19 / 26
Test Scoping トレイト の追加
トレイトの基本 • @Test や @Suite に属性を付与するのがトレイト • 用意されているトレイトのほか、カスタムトレイトも作れる @Test(.timeLimit(.minutes(1))) func addBookSuccessfully() { // テスト実行時間が1分を越えると、中断して不合格扱いになる } Test Scoping トレイトの追加 21 / 26
Test Scoping トレイト • カスタムトレイトのバリエーションが増えた • テストの前後にカスタムコードを実行するトレイトが作れる @Test(.mockAPICredentials) func example() { // ここの実行前後に、mockAPICredentials トレイトで定義した // カスタムコードが実行される } Test Scoping トレイトの追加 22 / 26
Test Scoping トレイトの実装 struct MockAPICredentialsTrait: TestTrait, TestScoping { func provideScope(for: ..., testCase: ..., performing function: ...) async throws { // ここに `function` を呼ぶカスタムコードを書く } } extension Trait where Self == MockAPICredentialsTrait { static var mockAPICredentials: Self { Self() } } Test Scoping トレイトの追加 23 / 26
Test Scoping トレイトの使いみち 正直、使いみちがあまり分かっていません。 • setUp / tearDown の実現? ‣ シンプルな init / deinit で足りる ‣ それで足りないような複雑なことをしたい場合があれば有益か • モックの挿入? ‣ モックの値はテスト内容に応じて変えたい場合が多いので、トレ イトだとやりづらい気がする Test Scoping トレイトの追加 24 / 26
まとめ
紹介した更新内容 Swift 6.1 / Xcode 16.3 で機能更新(2025 年 3 月) • UI テストのフレームワークが独立 • エラーのテストの改善 • パラメトライズテストの型推論 • 非同期処理のテストの改善 • Test Scoping トレイトの追加 まとめ 26 / 26