Repository navigation
Xcode Project CI
検証日: 2026年9月27日
CI 実行で、macOS と iOS Simulator のビルド成功後、macOS 単体テストが終了コード 65 で失敗した。終了コードだけでは原因を特定できず、この実行には assertion の詳細と .xcresult が残っていなかった。
結果バンドルの保存と失敗スイートの単独実行を追加した後続の CI 実行(コミット 2e2b2c37a58e7c14ef17e666c7197e6538d3e93c)で、次の結果を確認した。件数は引数別ケースを含む。
| 実行対象 | 結果 | 失敗内容 |
|---|---|---|
| macOS 単体テスト全体 | 402 件中 26 件失敗 | 歌詞 5 件、音量正規化 21 件がタイムアウト |
LazyLyricsLoadingTests 単独 |
11 件すべて成功 | — |
AudioLoudnessNormalizationTests 単独 |
21 件中 7 件失敗 | 全体実行と同じ待機タイムアウト |
歌詞テストでは、waitForReads の 3 秒待機後に Expectation failed: await probe.readCount >= count が記録されていた。音量正規化テストでは、waitFor の 5 秒待機で Timed out waiting for the controlled loudness measurement. と .timeout が記録されていた。
根本原因の有力候補は、音量測定のテスト用処理による Swift Concurrency のスレッド占有である。Task.detached から呼ばれる ControlledLoudnessMeasurement.measure() は NSCondition.wait でスレッドをブロックし、その解除にはテスト側の非同期処理が進む必要がある。Swift の実装者による説明でも、detached task は共有の協調スレッドプールを使い、別の処理による解除を待つブロッキングに注意が必要とされている。
スイートを単独で実行しても、内部のテストは並列実行される。このため、単独実行での失敗だけでは並列実行の影響を除外できない。ただし、今回の結果バンドルから確認できたのは待機タイムアウトまでであり、スレッド枯渇や、音量テストが歌詞テストへ及ぼす影響は未確定である。
同期的に待機する測定スタブの同時実行を抑えるため、AudioLoudnessNormalizationTests に @Suite(.serialized) を追加した。この指定は引数別ケースにも適用される。他スイートとの並列実行、アプリの音量測定処理、待機期限は変更していない。適用範囲は Swift Testing の公式資料で確認した。
ローカルの Xcode 27.0(27A266a)では、音量正規化スイート単独の 21 ケースと macOS 単体テスト全体の 402 ケースがすべて成功した。iOS Simulator 向けの build-for-testing も成功し、SwiftLint は重大な違反 0 件(既存の警告 34 件)だった。
CI 環境でのタイムアウト解消は、変更反映後に確認する。ローカルでの成功だけでは根本原因を確定できない。
ワークフローは全体実行の結果を AllUnitTests.xcresult に保存する。全体実行が失敗すると、歌詞・音量正規化の各スイートを別々に実行し、それぞれの結果も保存する。単独実行が成功しても全体実行の失敗は維持される。結果バンドルは macOS-test-results artifact に 14 日間保存される。
-
artifact をダウンロードし、各
.xcresultを Xcode で開く。CLI では次のコマンドで失敗内容を確認できる。xcrun xcresulttool get test-results summary --path /path/to/AllUnitTests.xcresult
-
全体実行とスイート単独実行の失敗行、assertion、所要時間を比較する。単独実行だけが成功する場合はスイート間の競合や実行負荷を、単独でも失敗する場合はスイート内の並列実行や実装を調べる。単独実行の成否だけで原因を断定しない。
-
直列化後も同じ待機タイムアウトが発生する場合は、測定スタブの同期ブロッキングを非同期の待機に変更し、単独実行と全体実行を比較する。歌詞テストの失敗も解消するか、全体実行で確認する。
Issueの元条件はXcode27.1 Beta/iOS27 Simulator。Beta同版が手元にないため、後続Xcode27.1 RC(27A9275)で検証した。VideoSpectrumAnalysisTestsとVisualizationSuppressionTestsの正弦波生成式は、Doubleの位相とFloatのmap戻り値へ型を明記して分割した。周波数/振幅/サンプル数/演算順序を維持し、同様の式の型コンテキストも確認した。
RCでは変更前後とも通常schemeのiOS Simulator build-for-testingがUI targetを含め成功した。修正後は関連23単体/4suitesが4.965秒で成功し、検索背景化を含む統合版の通常iPhone全単体809件/131suitesも57.248秒で成功した。元Betaの時間切れ再現や、変更前の全単体実行成功は確認していない。今回の型注釈がBeta失敗を解消したという因果まで主張しない。
RCでは既存packageを用い、generic/platform=iOS Simulator、arm64、CODE_SIGNING_ALLOWED=NOで通常schemeをbuild-for-testingした。単体の実行にはiPhone17e iOS27.0 Simulatorを指定した。修正前ログsimple-media-player-issue73-before.log、修正後simple-media-player-issues72-73-65-build.logと最終final-search-iphone-units.logはローカルに保全している。macOSの統合Release全単体816件/130suitesも成功し、SwiftLintは新規違反をbaselineへ追加していない。