生成されたXcodeプロジェクト
- Xcodeテストインサイトが設定されていること(自動生成されたスキームには
tuist inspect testポストアクションが含まれています。カスタムスキームではこれを追加する必要があります)。
Flakyテストとは、同じコードで複数回実行したときに異なる結果(合格または不合格)を返すテストのことです。これらはテストスイートへの信頼を損ない、誤った失敗の調査に開発者の時間を浪費させます。TuistはFlakyテストを自動的に検出し、時間経過に伴う追跡をサポートします。

Flaky検出の仕組み#
Tuistは以下の2つの方法でFlakyテストを検出します。
テストの再試行#
再試行機能を使用してテストを実行すると、Tuistは各試行の結果を分析します。ある試行では失敗し、別の試行では成功するテストはFlakyとしてマークされます。
-retry-tests-on-failureまたは-test-iterationsをtuist test経由で渡します。
tuist test --scheme MyScheme -- -retry-tests-on-failure -test-iterations 3

クロスラン検出#
テストの再試行を行わなくても、Tuistは同じコミットおよび同じスキームに対する異なるCIランの結果を比較することでFlakyテストを検出できます。あるCIランではテストが成功し、同じコミットとスキームの別のランでは失敗する場合、両方のランがFlakyとしてマークされます。
スキームは比較キーの一部です。同じテストでもスキームによって決定的に異なる動作をする可能性があるためです。例えば、特定のシミュレータデスティネーションに対してのみ有効なスナップショットテストや、異なるフラグでコンパイルされるテストターゲットなどが挙げられます。異なるスキームで同じコミットを2回実行した場合、それらは別の実行バリアントとして扱われ、互いをFlakyとしてフラグ付けすることはありません。
これは、再試行で捕捉できるほど一貫して失敗しないものの、依然として断続的なCI障害を引き起こすFlakyテストを検出するのに特に役立ちます。
Flakyテストの管理#
自動クリア#
検出とクリアは、プロジェクト上の自動化アラートを通じて実行されます。すべてのプロジェクトには、デフォルトの「Flakyテスト検出」自動化が用意されており、そのトリガーはテストをFlakyとしてマークし、リカバリーは、テストが構成されたリカバリー期間(デフォルト14日間)中に再トリガーされずに経過した場合にフラグをクリアします。設定 → 自動化で編集して、リカバリー期間を変更したり、リカバリーアクション(例:隔離解除も行う)を入れ替えたり、リカバリーを完全に無効にしてテストを手動でクリアするまでFlakyマークのままにするように設定できます。
手動管理#
テストケースの詳細ページから、テストをFlakyとして手動でマークしたり、マークを解除したりすることもできます。これは以下のような場合に便利です。
- 修正作業中に既知のFlakyテストを認識しておきたい場合
- インフラストラクチャの問題によりテストが誤ってフラグ付けされた場合
Flakyテストの隔離#
隔離は、Flakyテストを分離し、修正中にCIをブロックしないようにします。デフォルトでは手動アクションです。ダッシュボードのテストケース詳細ページから隔離、隔離解除、モードの切り替えを行います。ただし、設定 → 自動化の下にある自動化アラートに組み込むこともでき、テストがFlaky性の閾値を超えたときに自動的にミュート(またはスキップ)され、回復すると隔離解除されます。手動か自動かを問わず、すべての遷移はテストケースの監査ログに記録されます。
隔離されたテストは、以下の2つのモードのいずれかになります。
- ミュート: テストは引き続き実行されますが、
tuist testが失敗をマスクします。失敗は依然としてFlakyテスト検出器に供給されるため、ビルドを壊さずにテストを監視し続けることができます。積極的に調査中のテストにこのモードを選択してください。 - スキップ: xcodebuildは
-skip-testing <identifier>を受け取るため、テストは開始されません。新しい結果は生成されず、再度有効にするまでFlakyテストダッシュボードから除外されます。テストが壊れている、遅い、またはあまりにも持続的にFlakyで実行することがCI時間の無駄である場合にこのモードを選択してください。
隔離されたテストが合格として表示される理由#
- ミュートされたテストは引き続き実行されます。失敗したミュートテストは、テストケースラン上で失敗として記録され、Flakyとしてフラグ付けされます。テストごとのステータスは書き換えられません。上書きされるのは全体のテストランです。ラン内のすべての失敗テストケースがミュートされている場合、ラン全体は合格として報告されるため、ミュートされた失敗はCIを中断しません。
- スキップされたテストはまったく実行されないため、ダッシュボードにはテストの最後の実際の実行からのステータスが引き続き表示されます。そのスナップショットは数週間前のものかもしれません。
テストの実行#
tuist testは両方のモードを自動的に尊重します。
tuist test
スキップされたテストは-skip-testingとしてxcodebuildに渡され、開始されることはありません。ミュートされたテストは通常通り実行されます。失敗した場合、その失敗は結果のビルドステータスでマスクされます。
隔離を完全にバイパスし、ミュートおよびスキップされたテストを含めてすべてを実行するには:
tuist test --skip-quarantine
新しいテストのストレステスト#
ストレスゲートは、ブランチが追加したテストケースをそれぞれ新鮮なプロセスで複数回再実行し、Flakyであることが判明したものを報告します。数週間後ではなく、それを導入したプルリクエスト上で新しいFlakyテストを確認できます。
テストケースは、プロジェクトのデフォルトブランチで過去90日間にCIで実行されていない場合、またはその後そのブランチに着地したコミットで実行されていない場合に新規とみなされます。マージキューを使用する場合、キューが実行したテストケースは、キューのコミットが着地した時点で認識され、キューがそれをドロップした場合は新規のままとなります。コミットは、TuistがCIで収集するGit履歴を通じて照合されます。
有効化#
ゲートはデフォルトでオフになっています。モードを設定してください。
report: 各Flakyテストケースについて警告します。ランは依然として自身の結果に基づいて終了します。enforce: Flakyなテストケースはランを失敗させ、失敗したテストと同じ終了コードを返します。
どちらのモードでも、選択的テストは、次のランでFlakyな新しいテストケースを含むテストターゲットをスキップしません。ターゲットは再度実行され、ゲートはテストケースがすべての再実行に合格するまで再度ストレステストを行います。
reportで数週間開始し、enforceが何をブロックしていたかを確認してください。
パススルー引数の前に渡すか、TUIST_TEST_STRESS_NEW_TESTSを設定してCIレーンごとにモードを変更します:
tuist test --stress-new-tests report
各テストの再実行回数#
最初のパスでテストケースにかかった時間によって異なります:
| 最初のパス | 再実行 |
|---|---|
| 最大5秒 | 10 |
| 最大10秒 | 5 |
| 最大30秒 | 3 |
| 最大5分 | 2 |
| 5分以上 | 再実行なし |
再実行は最初のパスでビルドされたものを再利用します。パスは200件のテストケースまたは10分のいずれかに達すると停止し、どの制限に達したかを報告します。
ゲートが実行されない場合#
- 最初のパスがすでに失敗しています。まずそれらのテストを修正してください。
- プロジェクトにデフォルトブランチがないか、そのブランチでCIがまだ何も実行されていません。
- プロジェクトのテストケースの30%以上が新規のように見えます。それほど多くを再実行するのは価値に見合いません。これは、Tuistへのレポートを始めたばかりのプロジェクトや、一度に多くのテストを移動させる名前変更後のプロジェクトで発生することが予想されます。
Slack通知#
Slack連携でFlakyテストアラートを設定することで、テストがFlakyになった瞬間に通知を受け取れます。
Flakyおよび隔離状態のクエリ#
CLI#
tuist test caseコマンドツリーは、Tuistがテストケースについて追跡するすべてを公開します:
tuist test case list --flaky # only flaky test cases
tuist test case list --quarantined # only muted or skipped test cases
tuist test case show <test_case_id> # detail: flakiness rate, last status, run counts
tuist test case events <test_case_id> # audit log: marked_flaky, muted, skipped, ...
tuist test case run list <test_case_id> # run history with status and duration
tuist test case run show <test_case_run_id> # single run, including failure breakdown
これらすべてはスクリプト用に--jsonを受け入れます。
REST API#
同じデータはHTTP経由で利用可能です — ルート、フィルター、レスポンスフィールドの完全なリストについては、APIリファレンスのテストケースエンドポイントを参照してください。テストケースの状態(Flakyのマーク/解除、ミュート、スキップ)を変更するには、is_flakyまたはstateを指定してPATCH /api/projects/{account_handle}/{project_handle}/tests/test-cases/{test_case_id}を送信します。同じ変更はtuist test case updateとして、およびupdate_test_case Model Context Protocolツールとして利用可能です。