Xcode 6でコマンドラインを使ってテストを実行する(`destination`パラメータの調査)


Xcode 6になって、Simulatorの数が増えて、コマンドラインでテストを実行したい場合、
`xcodebuild`コマンドの情報を見ても、何を指定したらいいのかイマイチよくわからなかったので調査しました。


## コマンドラインでテスト実行

[Testing with Xcode](https://developer.apple.com/library/ios/documentation/developertools/conceptual/testing_with_xcode/A2-command_line_testing/A2-command_line_testing.html#//apple_ref/doc/uid/TP40014132-CH9-SW1 "Testing with Xcode") に記述があります。

指定する必要があるのは、`workspace`(or `project`)、`scheme`、`destination`です。
`scheme`は、テスト用に新規作成したほうがよいでしょう。
`destination`は、iOS Device、Simulator、OSバージョンなどを`key=value`ペアでカンマ区切りで指定します。

`destination`に何を指定すべきかは、`destination`に適当な`key=value`を指定してコマンドを実行すると一覧が表示されるのでそれで確認するのがよいでしょう。

```bash
xcodebuild test -workspace App.xcworkspace -scheme AppLogicTests \
-destination 'platform=Android,name=spam'
#[...]
Available destinations for the "AppLogicTests" scheme:
  { platform:iOS Simulator, id:1BE387A6-5747-40E5-B0CD-D09BF2ACB111, OS:7.0.3, name:iPad 2 }
  { platform:iOS Simulator, id:45E116FB-48BB-495E-90D3-130EE83FE36E, OS:7.1, name:iPad 2 }
  { platform:iOS Simulator, id:99C7DD9A-5706-441B-86E2-CA0132DA02E0, OS:8.0, name:iPad 2 }
  { platform:iOS Simulator, id:A22100E1-928C-4EF0-AD4A-1F7DFEEAC57F, OS:7.0.3, name:iPad Air }
  { platform:iOS Simulator, id:89C643E9-3031-4276-BCF5-E29A51489A8E, OS:7.1, name:iPad Air }
  { platform:iOS Simulator, id:08020160-40A3-4601-802D-187972CE1A42, OS:8.0, name:iPad Air }
  { platform:iOS Simulator, id:A3515C85-0346-4A01-BBD2-627BA2B6A96E, OS:7.0.3, name:iPad Retina }
  { platform:iOS Simulator, id:7BDF2853-6F74-45E8-BB33-D2F0890D7222, OS:7.1, name:iPad Retina }
  { platform:iOS Simulator, id:E291135E-53AA-4D3B-AD87-00F8E07E2BC9, OS:8.0, name:iPad Retina }
  { platform:iOS Simulator, id:E6A745D2-A83E-44D4-A846-F0CEF12DBD0F, OS:7.0.3, name:iPhone 4s }
  { platform:iOS Simulator, id:983928E1-3510-446F-9FF5-A378A7DB5A47, OS:7.1, name:iPhone 4s }
  { platform:iOS Simulator, id:52756176-9CED-44D0-88C9-FF12C9F7B8E5, OS:8.0, name:iPhone 4s }
  { platform:iOS Simulator, id:16039E7B-0A11-4B7A-9A4A-8E4B4A175DD0, OS:7.0.3, name:iPhone 5 }
  { platform:iOS Simulator, id:B4E21782-D230-4C06-BEF3-8D75B4D57474, OS:7.1, name:iPhone 5 }
  { platform:iOS Simulator, id:1E723270-8643-4DA1-8D08-EB6A498F34E4, OS:8.0, name:iPhone 5 }
  { platform:iOS Simulator, id:9A7A47D7-0D2D-4841-8210-6F96B8C4A7F1, OS:7.0.3, name:iPhone 5s }
  { platform:iOS Simulator, id:3269A923-701D-4736-855B-45B7DFF1C61D, OS:7.1, name:iPhone 5s }
  { platform:iOS Simulator, id:DE79D965-88D4-4516-A31C-82F359DE2836, OS:8.0, name:iPhone 5s }
  { platform:iOS Simulator, id:D0BF2D92-D746-4C40-A71C-9450443DDF27, OS:8.0, name:iPhone 6 Plus }
  { platform:iOS Simulator, id:0D98CF9F-D66E-4493-9D1E-8A17B8A06216, OS:8.0, name:iPhone 6 }
  { platform:iOS Simulator, id:392E2A71-0684-4F6D-A43A-7D96D96F9960, OS:8.0, name:Resizable iPad }
  { platform:iOS Simulator, id:FEC6D4A9-038F-45D3-96F3-E0248EC241F3, OS:8.0, name:Resizable iPhone }
```

例えば、iPhone 6のSimulatorでテスト実行したい場合は下記のように指定します。
OSを省略した場合、自動的に最新バージョンが利用されます(iPhone 6系はiOS 8.0しかないですが)

```bash
xcodebuild test -workspace App.xcworkspace -scheme AppLogicTests \
-destination 'platform=iOS Simulator,name=iPhone 6'
```

また、`name`と`OS`のかわりに、`id`を指定することも可能です。
iPhone 5s OS 7.1のSimulatorでテストする場合、下記のように指定します。


```bash
xcodebuild test -workspace App.xcworkspace -scheme AppLogicTests \
-destination 'platform=iOS Simulator,id=3269A923-701D-4736-855B-45B7DFF1C61D'
```

あと、一回で複数の`destination`を指定するのも可能なようなので、OSや端末ごとに同じテストを実行することができます。

```bash
xcodebuild test -workspace App.xcworkspace -scheme AppLogicTests \
-destination 'platform=iOS Simulator,id=3269A923-701D-4736-855B-45B7DFF1C61D' \
-destination 'platform=iOS Simulator,name=iPhone 6'
```


指定するパラメータがわかれば、下記のようにyamlやjsonなどの設定ファイルを用意して、GruntやRakeなどでタスクを自動生成してテスト実行することができるはずです。
これで、JenkinsだったりCIサービスなどを使ってテストができますね。

```.xctest-config.yml
default_settings:
  arguments: &default_arguments
    workspace: App.xcworkspace
    configuration: Debug
  platform: &default_platform
    iOS Simulator

AppLogicTests:
  latest:
    <<: *default_arguments
    destination:
      platform: *default_platform
      name: iPhone 6 Plus
  7.1:
    <<: *default_arguments
    destination:
      platform: *default_platform
      name: iPhone 5s
      OS: '7.1'

AppTests:
  latest:
    <<: *default_arguments
    destination:
      platform: *default_platform
      name: iPhone 6 Plus
  7.1:
    <<: *default_arguments
    destination:
      platform: *default_platform
      name: iPhone 5s
      OS: '7.1'
```