テストの分割などが可能なツール、FlankをiOSのUITestで導入してみます。
公式githubのREADME.mdももちろん見てください。
https://github.com/Flank/flank
Bitriseでの利用は別記事で触れています。
環境
- macOS Mojave 10.14.6(18G103)
- java version "1.8.0_241"
- Flank v8.1.0
- gcloud Google Cloud SDK 276.0.0, bq 2.0.52, core 2020.01.10, gsutil 4.47
環境の準備
私はおもむろにContributing
の項目の設定をはじめてしまいました。
使うだけの人はiOS example
の項目からはじめましょう。
java
ここではjdk-8u241-macosx-x64.dmg
を使いインストールしました。
https://www.oracle.com/java/technologies/javase-jdk8-downloads.html
$ java -version
java version "1.8.0_241"
Java(TM) SE Runtime Environment (build 1.8.0_241-b07)
Java HotSpot(TM) 64-Bit Server VM (build 25.241-b07, mixed mode)
java8にこだわらなくても良いと思いますがjava13だと動きませんでした。
gcloud CLI
インストールがまだの方はこちらから
https://cloud.google.com/sdk/gcloud?hl=ja
$ gcloud --version
Google Cloud SDK 276.0.0
bq 2.0.52
core 2020.01.10
gsutil 4.47
Google App Credentials
Google Credentials JSONを用意します。
ない方は以下から作成できます。p12とjsonが選べる場合はjson形式でokです。
https://console.cloud.google.com/apis/credentials/serviceaccountkey
storageへ書き込む権限が必要です。
ここでは以下のファイルがダウンロードされました。
kanari3-develop-ios-55a55aaa55aa.json
環境変数にexportします。
# ex: (例)
export GOOGLE_APPLICATION_CREDENTIALS='保存したパス/kanari3-develop-ios-55a55aaa55aa.json'
毎回流すのが面倒な方は.bash_profile
などに書いておきましょう。
iOS側
UITestが動くアプリを準備してください。
確認しておく項目は以下です。
- UITest用のScheme名
ここではUITestSampleUITests
となっています。
How-to-Use Flank
流れは以下のような感じです。
- UITest用アプリのBuild
- UITest用アプリのArchive
- Flankのclone
- ios.ymlを編集しておく
- Flankをビルド
- ビルドしたFlankのjarを実行
UITest用アプリのBuild
※ XCUITestでは、アプリ本体と別に、テスト用アプリをビルドして使います。
- XcodeのIDEではなくコマンドでビルドします。
- テストしたいアプリのルートで以下を実行してビルドします。
- ここではDerivedDataをプロジェクト以下に置きました。(commitしないようにしてください)
- MyProject、MyUITestsSchemeは適時読み替えてください。
xcodebuild -workspace MyProject.xcworkspace \
-scheme MyUITestsScheme \
-derivedDataPath MyDeriverdData \
-sdk iphoneos build-for-testing
UITest用アプリのArchive
以下のコマンドでzip化します。
cd MyDeriverdData/Build/Products ; \
zip -r MyTestApp.zip Debug-iphoneos MyUITestsScheme_iphoneos*-arm64e.xctestrun
MyUITestsScheme_iphoneos*-arm64e.xctestrun
の箇所はファイル名なので補完を効かせて入力しましょう
Flankのclone
cloneして中に移動します。
git clone git@github.com:Flank/flank.git && cd flank
ios.ymlを編集しておく
./test_runner/flank.ios.yml
まずは、最低限の設定をしてFlankでのテストを通しましょう。
Line番号はFlankのversionにより変わると思うので大体です。
ベースは書かれているのでコメントアウトを外して追記します。
- L:41
test:
アーカイブのパスです。
相対パスや絶対パスで入力します。
実運用ではflank.ios.ymlをアプリプロジェクトに内包すればパスは書きやすくなるかも知れませんね。
# L:41 ex:
test: /works/UITestSample/MyTests/Build/Products/MyTests.zip
- L:47
xctestrun-file:
xctestrunファイルのパスです。
# L:47 ex:
xctestrun-file: /works/UITestSample/MyTests/Build/Products/UITestSampleUITests_iphoneos12.3-arm64e.xctestrun
DeploymentTargetにより12.3
の箇所が変わるので実際のファイル名を確認してください。
Flankをビルド
cd test_runner/
./gradlew clean build fatJar
成功したときのログは以下
BUILD SUCCESSFUL in 1m 17s
16 actionable tasks: 16 executed
ビルドしたFlankのjarを実行
Flankを使ってFirebase Test LabでUITestを実行します。
java -jar ./build/libs/flank-*.jar firebase test ios run
flank-*
の箇所は私の環境ではflank-SNAPSHOT.jar
でした。
実行時のログは以下
$ java -jar ./build/libs/flank-*.jar firebase test ios run
IosArgs
gcloud:
results-bucket: test-lab-4d0240uptt2s2-j0tb4zpdrhnc5
results-dir: null
record-video: false
timeout: 15m
async: false
results-history-name: null
# iOS gcloud
test: /work/UITestSample/MyTests/Build/Products/MyTests.zip
xctestrun-file: /work/UITestSample/MyTests/Build/Products/UITestSampleUITests_iphoneos13.2-arm64e.xctestrun
xcode-version: null
device:
- model: iphone8
version: 12.0
locale: en
orientation: portrait
num-flaky-test-attempts: 0
flank:
max-test-shards: 1
shard-time: -1
num-test-runs: 1
smart-flank-gcs-path:
smart-flank-disable-upload: false
test-targets-always-run:
files-to-download:
# iOS flank
test-targets:
disable-sharding: false
project: kanari3-develop-ios
local-result-dir: results
RunTests
Uploading MyTests.zip .
Found xctest: /work/UITestSample/MyTests/Build/Products/Debug-iphoneos/UITestSampleUITests-Runner.app/PlugIns/UITestSampleUITests.xctest
isMacOS = true (mac os x)
nm -U "/work/UITestSample/MyTests/Build/Products/Debug-iphoneos/UITestSampleUITests-Runner.app/PlugIns/UITestSampleUITests.xctest/UITestSampleUITests"
nm -gU "/work/UITestSample/MyTests/Build/Products/Debug-iphoneos/UITestSampleUITests-Runner.app/PlugIns/UITestSampleUITests.xctest/UITestSampleUITests" | xargs -s 262144 xcrun swift-demangle
Smart Flank cache hit: 0% (0 / 1)
Shard times: 120s
1 test / 1 shard
Uploading UITestSampleUITests_iphoneos13.2-arm64e.xctestrun .
1 matrix ids created in 0m 5s
https://console.developers.google.com/storage/browser/test-lab-4d0240uptt2s2-j0tb4zpdrhnc5/2020-03-06_01-58-13.697000_pdKG/
PollMatrices
0m 1s matrix-71ucqbcx81avk iphone8-12.0 VALIDATING
0m 13s matrix-71ucqbcx81avk iphone8-12.0 PENDING
0m 25s matrix-71ucqbcx81avk iphone8-12.0 Starting attempt 1.
0m 25s matrix-71ucqbcx81avk iphone8-12.0 Checking Internet connection...
0m 25s matrix-71ucqbcx81avk iphone8-12.0 RUNNING
0m 56s matrix-71ucqbcx81avk iphone8-12.0 Internet connection stable!
1m 9s matrix-71ucqbcx81avk iphone8-12.0 Started device logs task
2m 27s matrix-71ucqbcx81avk iphone8-12.0 Stopped device logs task
2m 36s matrix-71ucqbcx81avk iphone8-12.0 Done. Test time = 60 (secs)
2m 36s matrix-71ucqbcx81avk iphone8-12.0 Starting results processing. Attempt: 1
2m 36s matrix-71ucqbcx81avk iphone8-12.0 Completed results processing. Time taken = 4 (secs)
2m 36s matrix-71ucqbcx81avk iphone8-12.0 FINISHED
2m 36s matrix-71ucqbcx81avk FINISHED
FetchArtifacts
.
Updating matrix file
CostReport
Physical devices
$0.08 for 1m
MatrixResultsReport
1 / 1 (100.00%)
ログ解説
ここでは成功率は1/1で100% PASSとなっていますが、Matrix単位なので、UITestが複数ケースあっても1/1となります。
GCPのストレージにMyTests.zipがアップロードされているのが確認できると思います。
金額は$0.08課金されています。
実行デバイスはFirebase Test Labのdefaultデバイスが自動的に選択されます。
確認したい方は以下
$ gcloud firebase test ios models list
┌─────────────┬───────────────────────┬─────────────────────┬──────────────────────────────────┐
│ MODEL_ID │ NAME │ OS_VERSION_IDS │ TAGS │
├─────────────┼───────────────────────┼─────────────────────┼──────────────────────────────────┤
│ ipad5 │ iPad (5th generation) │ 11.2,12.0 │ deprecated=11.2 │
│ ipadmini4 │ iPad mini 4 │ 11.2,12.0 │ deprecated=11.2 │
│ ipadpro_105 │ iPad Pro (10.5-inch) │ 11.2 │ deprecated=11.2 │
│ iphone11 │ iPhone 11 │ 13.3 │ │
│ iphone11pro │ iPhone 11 Pro │ 13.3 │ │
│ iphone6 │ iPhone 6 │ 11.4,12.2 │ deprecated=11.4 │
│ iphone6s │ iPhone 6s │ 10.3,11.2,11.4,12.0 │ deprecated=10.3, deprecated=11.2 │
│ iphone7 │ iPhone 7 │ 11.2,11.4,12.0,12.3 │ deprecated=11.2 │
│ iphone7plus │ iPhone 7 Plus │ 11.2,11.4,12.0 │ deprecated=11.2 │
│ iphone8 │ iPhone 8 │ 11.2,11.4,12.0 │ deprecated=11.2, default │
│ iphone8plus │ iPhone 8 Plus │ 11.2,11.4,12.0,12.3 │ deprecated=11.2 │
│ iphonese │ iPhone SE │ 11.2,11.4,12.0,12.3 │ deprecated=11.2 │
│ iphonex │ iPhone X │ 11.2,11.4,12.0,12.3 │ deprecated=11.2 │
│ iphonexr │ iPhone XR │ 13.2 │ │
│ iphonexs │ iPhone XS │ 12.0,12.1,12.3 │ │
│ iphonexsmax │ iPhone XS Max │ 12.0,12.1,12.3 │ │
└─────────────┴───────────────────────┴─────────────────────┴──────────────────────────────────┘
ステップアップ
Firebase Test LabのUITest録画機能を使ってみましょう
設定
ios.ymlのL:18のrecord-video:
をtrueに設定します。
record-video: true
実行結果
ログのhttps://console.developers.google.com/storage/browser/
の箇所にアップロードされたファイルが格納されています。
動画ファイルはここでは以下に保存されていました。
shard_0/iphone8-12.0-en-portrait/video.mp4
テスト失敗時
ログは以下のようになります。
MatrixResultsReport
0 / 1 (0.00%)
1 matrices failed
HtmlErrorReport written to /work/flank/test_runner/results/flank-uitest/HtmlErrorReport.html
Error: Matrix failed: matrix-71ucqbcx81avk FINISHED failure https://console.firebase.google.com/project/kanari3-develop-ios/testlab/histories/bh.49d8d135811054f7/matrices/8560953674081399197/executions/bs.9f408b536f2a9f54
テストレポートのURLが表示されていて親切ですね。
リンクに飛ぶと以下のような画面になります。
動画タブでは動画が再生できます。
textExample()
のテストケースを選択すると個別のエラーログが見れます。
TestCaseにXCFail("わざと失敗させました")
を挿入してみました。
管理
GCPのバケットがどんどん溜まっていくのでディレクトリを設定しましょう。
必要なファイルが埋もれるとまとめて消すときに事故のもとです。
# L:12 ex
results-dir: flank-uitest
Cloud Storageの無料枠 (5GB) も意識しましょう。
トラブルシューティング
GOOGLE_APPLICATION_CREDENTIALSが読めない
~/
に置くとFlankから読めないことがあるようです。
おわり
随時追記します。
シャードを分けた並列テストについては別記事を書く予定です!
次はBitriseからFlankを使う方法について触れます。
BitriseでもFlankを使ってFirebase Test LabでUITestしたい