View in English

  • メニューを開く メニューを閉じる
  • Apple Developer
検索
検索を終了
  • Apple Developer
  • ニュース
  • 見つける
  • デザイン
  • 開発
  • 配信
  • サポート
  • アカウント
次の内容に検索結果を絞り込む

クイックリンク

5 クイックリンク

ビデオ

メニューを開く メニューを閉じる
  • コレクション
  • トピック
  • すべてのビデオ
  • 利用方法

その他のビデオ

ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。

  • 概要
  • トランスクリプト
  • コード
  • テストの繰り返しによる信頼性の低いコードの診断

    テストの繰り返しは、最も信頼性の低いコードのデバッグにも役立ちます。テストプラン、Xcode、xcodebuild内の最大反復テスト、失敗するまでのテスト、失敗した場合の再試行などを使用して、バグやクラッシャを追跡し、Appを誰にとってもより安定したものにする方法を確認しましょう。 このセッションを最大限に活かしていただくためには、XCTestとテストプランによるテストの管理に精通していることが推奨されます。詳しくは、WWDC19の「Xcodeでテストする」をご確認ください。

    リソース

      • HDビデオ
      • SDビデオ

    関連ビデオ

    WWDC22

    • Xcode Cloud用の高速で信頼性の高いテストを作成する

    WWDC21

    • デジタルクラウン、トラックパッド、iPadポインタの自動化
    • Swiftのasync/awaitについて
    • XCTestで想定される失敗の容認
  • ダウンロード

    こんにちは WWDC 2021 へようこそ 私は XcodeのXCTest 担当のSuzyです このセッションではテストを 繰返す為のツールである テストリピートを使って 信頼性の低いコードの 診断方法について学びます

    App起動テストを実行する 過程で信頼性のない コードを実行するとテストが 失敗することがあります

    レースコンディション 環境の仮定 グローバルステート 外部サービス通信等を扱う際 このような不整合が 発生することがあります これらのバグは 再現が難しいため 追跡するのが難しいバグです このような不具合を 診断する方法の1つは テストを繰返し 実行することです Xcode 13で追加された テストの繰返しでは 停止条件を指定して 指定した回数まで テストを繰りす事ができます Xcodeは3つのテスト繰返し モードをサポートしています 1つ目のモードは Fixed iterations です テストの状態に関わらず 一定の回数だけ テストを繰返します Fixed iterationsは テストの信頼性を把握し 時間の経過と共に新しい テストが導入されても 信頼性を維持するのに 役立ちます 2つ目は Until failure です Until failureは 失敗するまで テストを繰返します 私はこのツールを使って テストの失敗を再現し デバッガで 検出するのが好きです 最後は Retry on failure です これは 指定された最大値まで 成功するまで テストを再試行します 最初失敗しても再試行で 最終的に成功する様な 信頼性の低いテストを 特定するのに便利です CIのテストでこのような 挙動が見られる場合 テスト計画で一時的に Retry on failure を有効にして 問題を解決するための 追加データを 収集することができます 失敗時の再試行には 実際の製品の問題が 隠されてる可能性がある事を 覚えておく必要があります 最初に失敗してから 最終的に成功する 機能もあるので このモードを一時的に使用し 失敗を診断するのが最善です 実際にどう機能するのか 理解を深めていきましょう 「IceCreamTruckCountdown」 という アイスクリームトラックが 家の前を通るまでの時間を 教えてくれる Appを作りました クッキー&クリーム があると嬉しいので 全てのフレーバーが 揃っているかを確認する為に testFlavorsという テストを書きました testFlavors は truckDepot から 取得したトラックがあります

    私はprepareFlavorsを 呼び出し 最後に 33種類のフレーバーが全て 揃っている事を表明します

    最近 Xcode Cloud のメイン ブランチで testFlavors が 時々失敗することに 気づきました もっと情報を集めるために テストプランを 一時的に設定し Test Repetition Modeを失敗時に 再試行するようにしました レポートナビゲータを見て クラウドのレポートを チェックしてみましょう

    テストが一貫して 失敗しているので 最後のテストをチェックして 情報を集めましょう

    最初のデバイスを開くと イテレーションのラベル があり このテストの 最初のイテレーション であることがわかります

    そして 他の行を すべて展開すると アサーションの失敗は すべて同じで この 最後のテストは 合格しています 1台のデバイスだけでなく すべてのテストが 一貫してパスすることを 期待していました この失敗をローカルで 再現してみましょう testFlavorsがある ファイルに行ってみましょう

    Controlキーを押し テスト用の ダイヤモンドをクリック Run "testFlavors()" Repeatedly をメニューから選択し テストの繰返し ダイアログを表示します ここでは 繰返しの 停止条件を選択したり 最大反復回数を設定したり Pause on Failure等の オプションを 設定することができます ここでは クラウドレポートで 発生した問題を 再現したいので 停止条件を最大反復回数を 経るように設定し 100回にしておきます

    では テストを実行してみます

    よし! テストは ローカルで失敗しました 失敗のアノテーションを クリックすると Xcode Cloudで起こったのと 同じエラーが表示され 100回中4回失敗しました これで この問題をデバッグ できる様になりました もう一度 Controlキーを押しながら testFlavorsのテスト ダイヤをクリックし Run "testFlavors() " Repeatedly を選択 しかし 今回は失敗した時に 停止するようにして 問題が起きた時に デバッグできるようにします Xcodeは自動的にPause on Failure を選択してくれるので デバッガでエラーを検出 することができます

    これで問題が解決しました トラックのフレーバーに 不整合があると わかっているので デバッガで トラックオブジェクト を見てみます

    既に prepareFlavors を呼び出して いるので flavorsが33で あるべき所が0になって いるのはおかしいですね この completionHandler の中に 入ってしまったのでしょうか ブレークポイントを追加して 「続行」をクリックします

    うーん なんか間違ってる気がします

    fruffleは内側のprepareFlavors completionHandlerではなく 外側のcompletionHandlerで 呼び出されています

    複数のcompletionHandler がある非同期イベントで 期待値が正しい場所で 満たされていない事が原因の かなり単純なバグです XCTestはSwift 5.5に対応しており 5async/await使用で テストを単純化し 二度と 起こらない様にできます このテストをasync/awaitを 使うように変換するには メソッドのヘッダーに async throws を追加します

    iceCreamTruckを truckDepotから 取得するのに "await " バージョンを使用します

    prepareFlavorsの "await " バージョンを使用します

    同じアサートですがトラック はオプションではないです

    このテストを もう一回実行して 修正されていることを 確認してみましょう Controlキーを押しながら Run "testFlavors()" Repeatedlyを選択し もう一度 Maximum Repetitionsを 停止条件として選択します

    やったー! このテストは 100回パスしました これで解決したと 確信したので テスト計画から 失敗時の再試行を削除して 変更をコミットする 準備ができました という訳で デスク上の使い方と テスト計画に設定することで CIでテストを 繰返し実行する方法の 1つを理解したところです それでは デモのようにCLIを使って テストを繰返し実行する 別の方法を説明します xcodebuildを 直接実行する場合 テストプランの設定を 上書きする xcodebuildフラグを 追加することができます

    test-iterationsに 数字を渡すと 固定回数のテストを実行でき また -retry-tests-on-failure や -run-tests-until-failure と 組み合わせると 他の停止条件と一緒に 使うことができます xcodebuildを使って同じ様に テストを実行するには テストの実行に使う基本の xcodebuildコマンドから始めて -test-iterationsを 100に設定し -run-tests-until-failureの フラグを追加します 要約すると テストの繰返しは 信頼性の低いコードを 診断するための ツールとして使用します 一貫性のないテストの 取り扱いについては 「XCTestで想定される失敗の容認」 をご覧ください Swiftのasync については 「Swiftのasync/awaitについて」 をご覧ください ご覧いただき ありがとうございます [音楽]

    • 2:39 - testFlavors

      func testFlavors() {
          var truck: IceCreamTruck?
      
          let flavorsExpectation = XCTestExpectation(description: "Get ice cream truck's flavors")
          truckDepot.iceCreamTruck { newTruck in
              truck = newTruck
              newTruck.prepareFlavors { error in
                  XCTAssertNil(error)
              }
              flavorsExpectation.fulfill()
          }
      
          wait(for: [flavorsExpectation], timeout: 5)
          XCTAssertEqual(truck?.flavors, 33)
      }
    • 6:31 - testFlavors: add async throws to method header

      func testFlavors() async throws {
          var truck: IceCreamTruck?
      
          let flavorsExpectation = XCTestExpectation(description: "Get ice cream truck's flavors")
          truckDepot.iceCreamTruck { newTruck in
              truck = newTruck
              newTruck.prepareFlavors { error in
                  XCTAssertNil(error)
              }
              flavorsExpectation.fulfill()
          }
      
          wait(for: [flavorsExpectation], timeout: 5)
          XCTAssertEqual(truck?.flavors, 33)
      }
    • 6:32 - testFlavors: use the async version of the ice cream truck

      func testFlavors() async throws {
          let truck = await truckDepot.iceCreamTruck()
              truck = newTruck
              newTruck.prepareFlavors { error in
                  XCTAssertNil(error)
              }
              flavorsExpectation.fulfill()
          }
      
          wait(for: [flavorsExpectation], timeout: 5)
          XCTAssertEqual(truck?.flavors, 33)
      }
    • 6:33 - testFlavors: use the async version of prepareFlavors

      func testFlavors() async throws {
          let truck = await truckDepot.iceCreamTruck()
          try await truck.prepareFlavors()
          XCTAssertEqual(truck?.flavors, 33)
      }
    • 6:50 - testFlavors: the truck is no longer optional

      func testFlavors() async throws {
          let truck = await truckDepot.iceCreamTruck()
          try await truck.prepareFlavors()
          XCTAssertEqual(truck.flavors, 33)
      }
  • 特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。

    クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。

Developer Footer

  • ビデオ
  • WWDC21
  • テストの繰り返しによる信頼性の低いコードの診断
  • メニューを開く メニューを閉じる
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    メニューを開く メニューを閉じる
    • アクセシビリティ
    • アクセサリ
    • App Extension
    • App Store
    • オーディオとビデオ(英語)
    • 拡張現実
    • デザイン
    • 配信
    • 教育
    • フォント(英語)
    • ゲーム
    • ヘルスケアとフィットネス
    • アプリ内課金
    • ローカリゼーション
    • マップと位置情報
    • 機械学習
    • オープンソース(英語)
    • セキュリティ
    • SafariとWeb(英語)
    メニューを開く メニューを閉じる
    • 英語ドキュメント(完全版)
    • 日本語ドキュメント(一部トピック)
    • チュートリアル
    • ダウンロード(英語)
    • フォーラム(英語)
    • ビデオ
    Open Menu Close Menu
    • サポートドキュメント
    • お問い合わせ
    • バグ報告
    • システム状況(英語)
    メニューを開く メニューを閉じる
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles(英語)
    • フィードバックアシスタント
    メニューを開く メニューを閉じる
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program(英語)
    • News Partner Program(英語)
    • Video Partner Program(英語)
    • セキュリティ報奨金プログラム(英語)
    • Security Research Device Program(英語)
    Open Menu Close Menu
    • Appleに相談
    • Apple Developer Center
    • App Store Awards(英語)
    • Apple Design Awards
    • Apple Developer Academy(英語)
    • WWDC
    Apple Developerアプリを入手する
    Copyright © 2025 Apple Inc. All rights reserved.
    利用規約 プライバシーポリシー 契約とガイドライン