xcodebuild testでは、-destinationでテストを実行する場所を指定する。値は、キー=値をカンマで区切った指定子である。

$ xcodebuild test -project [プロジェクト名].xcodeproj -scheme [スキーム名] -destination 'platform=macOS,arch=arm64'
$ xcodebuild test -project [プロジェクト名].xcodeproj -scheme [スキーム名] -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.1'

指定できる実行先は、-showdestinationsで調べる。

実行例はXcode 27.0、macOS 27.0.1のもの。

指定できる実行先を調べる

-showdestinationsは、スキームで使える実行先を一覧する。ビルドやテストは実行されない。

$ xcodebuild -project [プロジェクト名].xcodeproj -scheme [スキーム名] -showdestinations
...
	Destinations compatible with the "[スキーム名]" scheme:
		{ platform:macOS, arch:arm64, id:[MacのID], name:My Mac }
		{ platform:iOS, id:dvtdevice-DVTiPhonePlaceholder-iphoneos:placeholder, name:Any iOS Device }
		{ platform:iOS Simulator, id:dvtdevice-DVTiOSDeviceSimulatorPlaceholder-iphonesimulator:placeholder, name:Any iOS Simulator Device }
		{ platform:macOS, name:Any Mac }
		{ platform:iOS Simulator, arch:arm64, id:[シミュレータのID], OS:26.1, name:iPhone 17 }

	Destinations incompatible with the "[スキーム名]" scheme:
		{ platform:watchOS Simulator, arch:arm64, id:[シミュレータのID], OS:26.5, name:Apple Watch SE 3 (40mm), error:... }

「compatible」の欄の{ ... }の中のキー:値が、-destinationに指定できるキーと値である。Anyで始まる名前の実行先は、特定のデバイスを指さない汎用の実行先である。

「incompatible」の欄は、スキームがサポートしないプラットフォームの実行先である。ターゲットの「Supported Platforms」にwatchOSが含まれないと、watchOSのシミュレータは「incompatible」になる。

参考: xcrun simctl listでiOSシミュレータのデバイス・ランタイム一覧を絞り込む

指定子のキー

実行先の指定子に使ったキーは、次のとおりである。

キー値の例意味
platformmacOS、iOS Simulator、iOS実行先のプラットフォーム
nameiPhone 17デバイスの名前
OS26.1、latestOSのバージョン
idシミュレータのUDIDデバイスのID
archarm64、x86_64CPUのアーキテクチャ

-showdestinationsの一覧にあるキーで絞り込める。指定したキーに一致する実行先が複数あれば、先頭の1つが使われる。

macOSで実行する

Macで実行するときは、platform=macOSを指定する。

$ xcodebuild test -project [プロジェクト名].xcodeproj -scheme [スキーム名] -destination 'platform=macOS'

platform=macOSだけを指定すると、警告が出る。Apple SiliconのMacでは、arm64とx86_64の2つが一致するためである。

--- xcodebuild: WARNING: Using the first of multiple matching destinations:
{ platform:macOS, arch:arm64, id:[MacのID], name:My Mac }
{ platform:macOS, arch:x86_64, id:[MacのID], name:My Mac }

警告を避けるには、arch=arm64を加える。

$ xcodebuild test -project [プロジェクト名].xcodeproj -scheme [スキーム名] -destination 'platform=macOS,arch=arm64'

iOSシミュレータで実行する

iOSシミュレータで実行するときは、platform=iOS Simulatorに、nameとOSを加える。値にスペースを含むので、指定子全体をクォートする。

$ xcodebuild test -project [プロジェクト名].xcodeproj -scheme [スキーム名] -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.1'

シミュレータのIDで指定する方法もある。idを指定するときは、nameとOSは不要である。

$ xcodebuild test -project [プロジェクト名].xcodeproj -scheme [スキーム名] -destination 'platform=iOS Simulator,id=[シミュレータのID]'

idだけの指定も、platformなしで動いた。

$ xcodebuild test -project [プロジェクト名].xcodeproj -scheme [スキーム名] -destination 'id=[シミュレータのID]'

OSを省略すると最新のランタイムが対象になる

OSを省略すると、OS:latestとして探される。最新のランタイムに指定したデバイスがないと、見つからずに終了コード70で失敗する。

$ xcodebuild test -project [プロジェクト名].xcodeproj -scheme [スキーム名] -destination 'platform=iOS Simulator,name=iPhone 17'
xcodebuild: error: Unable to find a device matching the provided destination specifier:
		{ platform:iOS Simulator, OS:latest, name:iPhone 17 }

	The requested device could not be found because no available devices matched the request.
...
$ echo $?
70

実行例のMacには、iPhone 17がiOS 26.1のランタイムにだけあり、最新のランタイムはiOS 26.5だった。OS=26.1を加えると、実行できる。複数のランタイムをインストールしている環境では、OSも指定する。

存在しないデバイス名でも、同じエラーで終了コード70になる。

$ xcodebuild test -project [プロジェクト名].xcodeproj -scheme [スキーム名] -destination 'platform=iOS Simulator,name=iPhone 99,OS=26.1'
xcodebuild: error: Unable to find a device matching the provided destination specifier:
		{ platform:iOS Simulator, OS:26.1, name:iPhone 99 }

nameを省略したOS=26.1だけの指定と、26のようにマイナーバージョンを省略したOS=26は、どちらも見つからず、終了コード70で失敗した。nameと、26.1のようなバージョン全体を、一緒に指定する。

generic/platformではテストできない

generic/platform=iOS Simulatorのように、generic/を付けた実行先は、特定のデバイスを指さない汎用の実行先である。buildは成功する。

$ xcodebuild build -project [プロジェクト名].xcodeproj -scheme [スキーム名] -destination 'generic/platform=iOS Simulator'
** BUILD SUCCEEDED **

testは、デバイスがないので失敗する。

$ xcodebuild test -project [プロジェクト名].xcodeproj -scheme [スキーム名] -destination 'generic/platform=macOS'
xcodebuild: error: Failed to build project [プロジェクト名] with scheme [スキーム名].: Cannot test target “[ターゲット名]Tests” on “Any Mac”: Tests must be run on a concrete device
$ echo $?
70

generic/platform=iOSのようなビルド用の指定は、xcodebuild buildで使う。testでは、platform=macOSやidのように、具体的なデバイスを指定する。

-destinationを省略する

-destinationを省略したxcodebuild testは、警告を出して、一致する実行先の先頭で実行される。

--- xcodebuild: WARNING: Using the first of multiple matching destinations:
{ platform:macOS, arch:arm64, id:[MacのID], name:My Mac }
{ platform:macOS, arch:x86_64, id:[MacのID], name:My Mac }
{ platform:iOS, id:dvtdevice-DVTiPhonePlaceholder-iphoneos:placeholder, name:Any iOS Device }
...

実行例では、My Macのarm64でテストが実行された。実行されたデバイスは、テスト結果の.xcresultから確認できる。

$ xcrun xcresulttool get test-results summary --path [結果の.xcresult] | grep -E '"(deviceName|platform)"'

実行先を省略すると、プロジェクトのサポートするプラットフォームや、接続しているデバイスで、結果が変わる。CIでは、-destinationを明示する。

複数の実行先を指定する

-destinationは、繰り返して指定できる。同じプラットフォームの2つのシミュレータを指定すると、両方でテストが実行された。

$ xcodebuild test -project [プロジェクト名].xcodeproj -scheme [スキーム名] \
    -destination 'platform=iOS Simulator,id=[シミュレータのID]' \
    -destination 'platform=iOS Simulator,id=[別のシミュレータのID]'
** TEST SUCCEEDED **

プラットフォームが異なる実行先を同時に指定すると、実行例の環境ではxcodebuildがクラッシュして、終了コード133で終了した。macOSとiOS Simulatorの2つを指定した場合である。プラットフォームごとに、xcodebuild testを分けて実行する。

どちらの方法を選ぶか

やりたいこと-destination
Macでテストするplatform=macOS,arch=arm64
特定のiOSシミュレータでテストするplatform=iOS Simulator,name=[デバイス名],OS=[バージョン]
シミュレータをIDで固定するplatform=iOS Simulator,id=[シミュレータのID]
ビルドだけするgeneric/platform=[プラットフォーム]

指定できる値は、-showdestinationsで確認する。テストを実行するスキームには、テストターゲットが含まれている必要がある。

参考: 【Xcode】Shared schemeをGit管理してCIのxcodebuildで使う (xcscheme)