Maestroを用いたE2EテストでApp Checkを突破する方法
はじめに
Firebase App Checkは不正なクライアントが Firebase リソースにアクセスすることを防ぐための仕組みです。
iOS Simulator のような開発環境は不正なクライアントと見做されてしまうため、特別にデバッグトークンを App Check に登録する必要があります。
このデバッグトークンはデバイス毎に異なり、またアプリをインストールする度に新たに生成されます。
この新たに生成されるという挙動が Maestro でテストを実行する際に問題になります。
Maestro での問題
Maestro のように対象のアプリを自動操作して E2E テストを実行する際、Firebase リソースにアクセスするために App Check のデバッグトークンが必要になります。
しかし前述したようにデバッグトークンは毎回新たに生成されるため、テストのたびに手動で登録する必要が出てきます。
App Check の公式の方法として、Environment Variables の FIRAAppCheckDebugToken
に任意の値を入れることで、任意のデバッグトークンを利用することはできます。
しかし、この方法はあくまでxcodebuild test
など Xcode からアプリを実行する時にだけ有効になるものであり、既にインストールされたアプリを操作する Maestro では適用されません。
つまりなんとかして iOS Simulator の環境変数のFIRAAppCheckDebugToken
に値を入れる必要があります。
解決方法
実はSIMCTL_CHILD_
というプレフィックスの環境変数は iOS Simulator に渡すことができます。
xcrun simctl boot
の説明にも書かれています。
xcrun simctl boot
Boot a device or device pair.
Usage: simctl boot <device> [--arch=<arch>] [--disabledJob=<job>] [--enabledJob=<job>]
--arch=<arch> Specify the architecture to use when booting the simulator (eg: 'arm64' or 'x86_64')
--disabledJob=<job> Disables the given launchd job. Multiple jobs can be disabled by passing multiple flags.
--enabledJob=<job> Enables the given launchd job when it would normally be disabled.
Multiple jobs can be enabled by passing multiple flags.
If you want to set environment variables in the resulting environment, set them in the calling environment with a SIMCTL_CHILD_ prefix.
その仕様を基にして以下のスクリプトを作成しました。
ポイントは SIMCTL_CHILD_FIRAAppCheckDebugToken
という環境変数を設定してから、iOS Simulator を起動することです。
# iOS Simulatorに渡したいFIRAAppCheckDebugTokenにプレフィックスを追加してexport
# ハードコードしていますが、実際は`.env`などから参照してコミットしないようにしましょう
export SIMCTL_CHILD_FIRAAppCheckDebugToken="17A9AC77-BE74-4DCA-8628-981D39E80785"
# テストを実行するiOS Simulatorの名前
# 事前にSimulatorは作成しておいてください。起動しておく必要はありません。
TEST_DEVICE_NAME="E2E Test"
# アプリをビルドする
# 今回はFlutterですが、別のフレームワークでも同じだと思います
APP_PATH="build/ios/iphonesimulator/Runner.app"
rm -rf "$APP_PATH"
fvm flutter build ios --debug --simulator --flavor stg
# シミュレータを起動する
# 既に起動している場合は再起動
TEST_DEVICE_UDID=$(xcrun simctl list devices --json | jq -r ".devices[][] | select(.name == \"$TEST_DEVICE_NAME\") | .udid")
xcrun simctl shutdown "$TEST_DEVICE_UDID" || true
xcrun simctl boot "$TEST_DEVICE_UDID"
# アプリをインストール
xcrun simctl install "$TEST_DEVICE_UDID" "$APP_PATH"
# Maestroを実行
maestro test .maestro/test.yml
# テスト用のiOS Simulatorをシャットダウン
xcrun simctl shutdown "$TEST_DEVICE_UDID" || true
参考
結果
最後のチャットっぽい画面に到達するためには Firebase Authentication で匿名認証が成功している必要があるので、無事にデバッグトークンで App Check を突破できていることがわかります。
Discussion