2026-04-23 レンタル クラウド Mac CI:iOS テストプラン、並列 XCTest、xcresult 切り分け
iOS QA オーナーとCI 保守者は、香港 / 日本 / 韓国 / シンガポール / 米国のレンタル Apple Silicon Mac で xcodebuild test を回すと、突発の -only-testing にはすぐ限界が来ます。本2026-04-23 ランはテストプランの標準化、宛先ごとの並列化、オブジェクト ストアへ安定名で xcresult を送る手順を示します。ヘッドレス Simulator テスト、DerivedData + xcresult の分離、並列アーカイブの拡散の補完です。
リモート CI にテストプランが要る理由
*.xctestplan は版管理された意図です。デフォルトのテストターゲット、オプション、環境変数行列を列挙し、チームが Git でレビューできます。巨大なシェル文字列を CI の YAML に埋めるより上です。特に、ポイント リリースのあと「どの構成が本当に走ったのか」と PM に聞かれたときに効きます。プランを単一のスキームに結び、スキームは安定させます。Debug と Release、アドレス サニタイザ、不安定な UI スイートの一時無効化はプランでモデル化し、テストを消さないで済ませます。
テストプランとスキームのみ:判断表
| 方針 | 向く場面 | SSH 上の運用性 |
|---|---|---|
コミット済み .xctestplan + -testPlan 名前 |
ノートとビルダーで再現。PR で差分 | 高—シャードあたり 1 コマンド |
スキーム既定 + -only-testing |
スパイクとホットフィックス レーン | 中—YAML の文字列が散らかる |
| 別スキームにテストターゲットを分割 | 無関係なアプリが同居するモノレポ | 低—スキームの二重管理 |
xcodebuild テスト起動の青写真
ホストで検証した Xcode に DEVELOPER_DIRをピン留めし、ジョブごとに Derived Data と明示的な結果バンドル パスでテストを走らせます。パスにジョブ ID を入れて、セルフホスト ランナーや社内スケジューラとの相関を簡単にします。
DEVELOPER_DIR=/Applications/Xcode.app xcodebuild test -workspace App.xcworkspace -scheme App -testPlan Nightly -destination 'platform=iOS Simulator,name=iPhone 16' -resultBundlePath "$CI_RESULTS/run-${CI_SHARD_ID}.xcresult" -derivedDataPath "$CI_DERIVED_DATA/${CI_SHARD_ID}"
xcodebuild test を2~4 同時までを予算化。
並列レーン、シャード、キュー
2 つの独立した軸があります。(a) 1 ホスト上の複数シミュレーターと、(b) 宛先 1 つずつの子ジョブ。(a) は費用には魅力的ですが、CoreSimulator とディスク I/O を非線形に鈍らせます。(b) はシンガポールや米国東部の本格チームの扇状実行に近づきます。各シャードは CORESIMULATOR_HOST 接頭辞と Derived Data を専有し、独自の *.xcresultをアップロードします。並列 xcodebuild の記事のキュー規律を再利用し、テスト向けの再試行予算と、アーカイブ ジョブより 20~35% ゆるいシャードあたりタイムアウトを付けます。XCTest の起動のばらつきは本物です。
シャードの帰属、命名、再実行
子ジョブに Git 名とは独立した安定した CI_SHARD_IDを与えます。スラッシュや絵文字入りのブランチ名は素朴なシェル glob を壊します。オペが YAML を開かずログを読めるよう、indexとcountを ID に埋めます。例:test-3-of-12はページャ スクリプトでは shard-uuidより分かりやすい。「失敗したテストだけ再実行」では、同じ DEVELOPER_DIRと resultBundlePath 族を保ったまま、失敗したバンドル ID だけ -onlyTesting: リストに再マッピングします。こうすれば、ほぼ同じ名前の無関係な 2 つ目 xcresultがストレージ バケットで衝突しません。マージ条件が「全緑」なら、再実行ポリシーが新しいシャード ラベルを許すか曖昧にせず文書化します。曖昧さはフレークを方針インシーデントに変えます。
ユニットは数分で終わり、UIは昼を超える混成パイプラインでは、遅いシャードに速いフィードバックを阻ませないでください。部分的な xcresultをステージング接頭辞に上げ、最後のシャードが通るまで「リリース」へ昇格させません。ダッシュボードは未完成のランから壁時の進行を出せても、本線の未完成と本線の緑を混ぜないようにします。DerivedData の記事の分離と相性が良く、同じ NVMe 上の兄弟シャードを触らず各シャードがクリーンアップでルートを消せます。
xcresult バンドル、マージ、保管するもの
各 xcresultは自己完結のテストレポートです。Xcode バージョン横断で保証されない方法で「ディスク上でマージ」しようとするより、シャードごとに 1 つを保ちます。下流では、品質ダッシュ向けに CI で JUnit や JSON へエクスポートしながら、インタラクティブ切り分け用に生 xcresultも保管するチームが多いです。保持は dSYM と同じ NVMe 方針に揃え、ビルドとテストを共有ホストで回す場合の表は dSYM とクラッシュ シンボリケーションを参照。
ベアメタル上 XCTest のフレーク切り分け表
| パターン | 想定原因 | 最初の手 |
|---|---|---|
| 6 回に 1 回失敗、UI + アニメ触り | タイムアウト対シム描画のばらつき | アニメを安定化。タイムアウト引き上げ。成果物に画面録画 |
| 1 シャードでクラス全滅 | シャード固有の環境、シード欠落 | 環境同値を主張。共有ボリュームを読専でマウント |
| 月曜のあと全シャードが遅い | OS 修正 + シミュレーター ランタイム変更 | p95 を再ベース。Xcode/ランタイム版を明示的に固定 |
NVMe、1~2 TB オプション、「なぜ CI を無制限に?」
テスト レーンはアーカイブ専用より一時 I/Oを速く乗せます。レンタル Mac の1 TB か 2 TBで、週次スイープを計画:緑のブランチ向け 7 日越し xcresult 削除。既定ブランチは30 日。App Store Connect に使うタグに対応は90 日—コンプラが締めます。署名の怪しさとテストの怪しさが混ざるときは、キーチェーンとプロビジョニングの手順を再確認し、XCTest 出力の読み違いを防ぎます。
関連 MacXCode ガイド
本ランを Simulator テスト基礎、アクセス パターン向け ヘルプ、テストとアーカイブ フリートを分ける ノード選定に接続。
FAQ:ヘッドレスでのテストプラン
| 質問 | 実践的な答え |
|---|---|
| テスト デバッグに VNC は? | 自動化なら稀—成果物を使い、UI 向けのブレークグラスとして VNC。 |
| Mac あたりシャード数は? | UI テストなら CPU コア / 3 から。1 週 p95 が安定してから上げる。 |
| 1 プランにユニット + UI 混在? | 小アプリなら可。大規模リポはレイヤーでプラン分け、クリティカル パスを短く。 |
XCTest 重い CI には Mac mini M4 ベアメタル
MacXCode のMac mini M4は、CoreSimulator の性能と、騒がしい隣人のハイパーバイザ越しに置かれない NVMe を再現性高く扱います。XCTest p95 のメトリクスが本当に見る面です。香港 · 日本 · 韓国 · シンガポール · 米国のリージョンでテスト用ビルダーをアーカイブの隣に置き、同じSSHの流儀、成果物多めなら 1~2 TB。再試行予算が I/O か CPU か、テストプランの誤設定でない限り、料金から弾力よくノードを足せます。