xcrun simctl pushは、JSON形式のAPNs(Apple Push Notification service)ペイロードを使い、実際にプッシュ通知サーバーを用意しなくてもシミュレータにプッシュ通知を送れるサブコマンドである。

基本的な使い方

apsキーを含むJSONファイルを用意し、対象アプリのbundle identifierとともに指定する。

{
  "aps": {
    "alert": {
      "title": "テスト通知",
      "body": "これはテストです"
    },
    "sound": "default"
  }
}
$ xcrun simctl push booted com.example.myapp push.json
Notification sent to 'com.example.myapp'

log streamで確認すると、usernotificationsdが通知を受け取り、対象アプリに配信されていることが分かる。

ペイロード内で対象アプリを指定する

JSONペイロードのトップレベルにSimulator Target Bundleキーを含めると、コマンド側でbundle identifierを指定する引数を省略できる。

{
  "Simulator Target Bundle": "com.example.myapp",
  "aps": {
    "alert": {
      "title": "ペイロード内指定テスト",
      "body": "bundle identifier引数を省略"
    }
  }
}
$ xcrun simctl push booted push.json
Notification sent to 'com.example.myapp'

標準入力からペイロードを読み込む

ファイルパスの代わりに-を指定すると、標準入力からペイロードを読み込める。

$ cat push.json | xcrun simctl push booted com.example.myapp -
Notification sent to 'com.example.myapp'

CIやスクリプトの中でペイロードを動的に生成してそのまま送りたい場合に使える。

ペイロードの制約に違反するとエラーになる

ヘルプに記載されているとおり、ペイロードにはいくつかの制約がある。 実際に試したところ、それぞれ次のようなエラーになった。

apsキーが無い場合。

$ xcrun simctl push booted com.example.myapp invalid.json
An error was encountered processing the command (domain=NSPOSIXErrorDomain, code=22):
Simulator device failed to complete the requested operation.
Invalid argument
Underlying error (domain=NSPOSIXErrorDomain, code=22):
	Notification payload is missing the aps key
	Invalid argument

トップレベルがオブジェクトでない(配列など)場合。

$ xcrun simctl push booted com.example.myapp array.json
An error was encountered processing the command (domain=NSPOSIXErrorDomain, code=22):
JSON root is not an object
Invalid argument

存在しないアプリを指定してもエラーにならない

実際に試したところ、インストールされていないbundle identifierを指定してもエラーにはならず、Notification sent to '...'と表示された。

$ xcrun simctl push booted com.example.nonexistent push.json
Notification sent to 'com.example.nonexistent'

log streamで確認すると、LaunchServicesfailed to find bundle record for com.example.nonexistentというログを出しているにもかかわらず、通知自体はSpringBoardの通知センターに登録されていた。 存在しないアプリ宛でもコマンド自体は成功したように見えるため、bundle identifierのタイプミスに気づきにくい。 log streamや実機のスクリーンショットで、意図したアプリに通知が届いているか確認した方がよい。

活用例: プッシュ通知UIのテスト自動化

実際のAPNsサーバーやデバイストークンを用意しなくても、任意のペイロードでプッシュ通知の受信・表示をテストできる。 CIに組み込めば、通知の文言や表示内容のバリエーションを、実際のプッシュ配信基盤を経由せずに機械的に検証できる。