[iOS] コマンドラインからUnit Testを行う

CI上でしか再現していないUnit Testの問題を調査している時に調べたメモを共有しておきます。

xcprettyを使うとxcodebuildが出力するログを色付きで綺麗に表示することができたり、結果を整形済みhtmlとして出力してくれるので、Xcodeによるログ出力より見やすく開発効率が上がるかもしれません。

- macOS High Sierra 10.13.2
- Xcode 9.2

---
# :iphone: iOSシミュレータ一覧表示
```
$ xcrun instruments -s
```
シミュレータ一覧がそれぞれのIDや名称とともに表示されます。
目当てのシミュレータが表示されない場合、xcode-selectが別のバージョンを指している可能性があります。

```
$ sudo xcode-select --switch /Applications/Xcode9.2.app
```
もしくは、`Xcode > Preferences > Locations > Command Line Tools` で選択変更してください。


# :tools: テスト開始
## :calling: シミュレータ起動
```
open "/Applications/Xcode9.2.app/Contents/Developer/Applications/Simulator.app" "--args" "-CurrentDeviceUDID" "<simulator_id>"
```
Xcodeのバージョン, `<simulator_id>` は環境に合わせて変更してください。
- `<simulator_id>` ... シミュレータのID

## :clipboard: テスト実行
```
$ set -o pipefail && env "NSUnbufferedIO=YES" xcodebuild "-workspace" "<path_to_workspace>" "-scheme" "<scheme_name>" "build" "test" "-destination" "id=<simulator_id>" | xcpretty "--color" "--report" "html" "--output" "<path_to_result_file>"
```
以下は環境に合わせて変更してください。
- `<path_to_workspace>` ... xcworkspaceのパス
- `<scheme_name>` ... スキーム名
- `<simulator_id>` ... シミュレータのID
- `<path_to_result_file>` ... テスト結果ファイルの書き出し先パス

例:

```
$ set -o pipefail && env "NSUnbufferedIO=YES" xcodebuild "-workspace" "myapp.xcworkspace" "-scheme" "myapp" "build" "test" "-destination" "id=57616E4F-D952-48AB-8F52-F0BF0BF3C1FF" | xcpretty "--color" "--report" "html" "--output" "xcode-test-results-myapp.html"
```

## :pencil2: 説明
### :heavy_dollar_sign: **set**
変数の値を設定する。
#### -o pipefail
```
If set, the return value of a pipeline is the value of the last (rightmost) command to exit with a  non-zero  status, or zero if all commands in the pipeline exit successfully.  This option is disabled by default.
```
途中のコマンドが異常終了したときにコマンド全体の返り値がその値となるよう設定。

### :heavy_dollar_sign: **env**
#### NSUnbufferedIO=YES
```
If set to YES, Foundation will use unbuffered I/O for stdout (stderr is unbuffered by default)
```
FoundationがstdoutにバッファされていないI / Oを使用する設定。  
他にも `NSZombieEnabled` `NSDeallocateZombies` など昔世話になったことがあるやつが設定可能なようです。  
https://developer.apple.com/library/content/technotes/tn2239/_index.html

### :heavy_dollar_sign: **xcodebuild**
#### -workspace
workspaceのパスを指定します。
`-workspace` か `-project` どちらかを指定する必要があります。

#### -scheme
指定可能な一覧は以下で確認できます。  

```
$ xcodebuild -list -workspace <project_name>.xcworkspace
```
```
$ xcodebuild -list -project <project_name>.xcodeproj
```

#### -destination
key=valueを,(カンマ)区切りで指定します。 `id`を指定するのが手っ取り早い。  
他には、`platform` `OS` `name` `arch` などが指定できるようです。

### :heavy_dollar_sign: **xcpretty**
詳細は[こちら](https://github.com/supermarin/xcpretty)
#### --color

#### --report
html以外のスタイルはよくわからんので試していません。
- `junit` ... JUnit-style XML
- `html` ... simple HTML
![simple HTML](https://camo.githubusercontent.com/ee976fecb1b3441951d98a4436bc3c7d6775fe09/687474703a2f2f692e696d6775722e636f6d2f30526e757833762e676966)
- `json-compilation-database` ... JSON compilation database

#### --output
reportを保存するパス


# :books: 参考
- [Technical Note TN2239 iOS Debugging Magic](https://developer.apple.com/library/content/technotes/tn2239/_index.html)
- [Technical Note TN2339 Building from the Command Line with Xcode FAQ](https://developer.apple.com/library/content/technotes/tn2339/_index.html)
- [GitHub supermarin/xcpretty](https://github.com/supermarin/xcpretty)