merpay Tech Talk ~for iOS Engineers~ https://mercari.connpass.com/event/197804/
参考 メルペイ iOS にスナップショットテストを導入した話https://engineering.mercari.com/blog/entry/ios-snapshot-test-case/
swift-snapshot-testingでSnapshot Testingを 効率化 merpay Tech Talk ~for iOS Engineers~ 2020 年 12 月 18 日 #merpay_techtalk
View Slide
Who am I ● Name ● 佐藤剛士(さとうたけし) ● Company ● Merpay, Inc.(2019/01 ~) ● Role ● Software Engineer (iOS) ● Account ● Twitter: @hatakenokakashi ● Facebook: 佐藤剛士 ● GitHub: SatoTakeshiX
今日話すこと ● Snapshot Testingの位置づけ ● メルペイが実施していたSnapshot Testing ● swift-snapshot-testingの紹介 ● swift-snapshot-testingの苦手分野 ● swift-snapshot-testingの導入方針 ● 実行端末を削減して実行時間を短縮 ● 出力画像ガチャ問題 ● Snapshot Testingを開発フローに導入しやすくする
Snapshot Testingの位置づけ 種類 目的 実行時間Unit Test ロジックを担保する 小Snapshot Testing Viewの画像を出力しレイアウトを確認中UI Test 実際のユーザーとほぼ同じ環境でアプリを動かし動作を確認大
メルペイが実施していた Snapshot Testing
https://engineering.mercari.com/blog/entry/ios-snapshot-test-case/
iOSSnapshotTestCase
使っていくうちにいくつか問題が出てきた ● 実行時間の増加 ● 出力画像ガチャ問題
実行時間の増加 ● iOSSnapshotTestCaseはキャプチャするViewサイズは自分で作らないといけない ● UIScreen.main.boundsでWindowを作成し、そのWindowのrootViewControllerに対象のViewControllerを代入していた ● 複数端末をキャプチャするために、実行端末を増やしていた ● iPhone SE, 6s, 7, 8, Xs, Xr, X, 11 Pro, iPadの10種類 ● そのため、実行時間が増えていた
iOSSnapshotTestCaseのコード
実行時間の増加 Unit Testよりもsnapshot testのほうが時間がかかっている
出力画像ガチャ問題 もともとの画像 テストで出力された画像
公式のIssue ● Test results depends on Mac device #109 ○ 2019年10月投稿 ○ https://github.com/uber/ios-snapshot-test-case/issues/109 ● Catalinaにバージョンアップしたときから画像の差異が出るようになった ● Xcode 11からシュミレーターのプロセスにGPUが使われるようになったそう ○ GPUのベンダーによって処理が異なる? ● 透過処理の画像を使うと時々差異が出てしまう
swift-snapshot-testingの紹介
swift-snapshot-testingとは? ● Swiftと関数型言語を解説するWebマガジンPoint-Freeが運営 ● Swiftで実装 ● 各端末の画面サイズのプリセットあり ○ iPhoneSE, 8, 8 Plus, X, XsMax, Xr, iPadMini など ○ iPadは縦向き、横向きを指定可能 ● 画像だけでなく、View階層をtextファイルに出力も可能 ● Dynamic TypeのSnapshot Testにも対応 ● SwiftUI対応
swift-snapshot-testingのテストコード
swift-snapshot-testing
Dynamic Type テストコード
Dynamic Type 出力画像
swift-snapshot-testingの 苦手分野
swift-snapshot-testingの苦手分野 ● window全体を撮るスナップショットが苦手 ○ https://github.com/pointfreeco/swift-snapshot-testing/issues/279 ● ポップアップやハーフモーダルの撮影が該当 ● 自分でUIApplication.shared.windowsからwindowを作成
swift-snapshot-testingの導入方針
swift-snapshot-testingの導入方針 ● メルペイではポップアップやハーフモーダルなどのWindow全体を撮影する画面が多くある
swift-snapshot-testingの導入方針 ● iOSSnapshotTestCaseと併用して使用する ○ Window全体のスナップショットはiOSSnapshotTestCase ○ View自体のスナップショットはswift-snapshot-testing ● swift-snapshot-testing用のtargetを追加 ○ iOSSnapshotTestCase用のtargetはすでに追加済み ● すでに実装したスナップショットテストは徐々にswift-snapshot-testingへ移行
実行端末を削減して 実行時間を短縮
実行端末を削減して実行時間を短縮 ● swift-snapshot-testing導入後、2020年9月、10端末で実行していたSnapshot Testを1端末に削減 ● 半分ほどにテスト時間を短縮
swift-snapshot-testingの導入 2020年9月のとあるworkflow結果
出力画像ガチャ問題
出力画像ガチャ問題 ● どうやっても解決できず ● iOSSnapshotTestCaseもswift-snapshot-testingも画像出力処理は同じ実装 ● しきい値を下げることで解決 ○ precisionプロパティ ● swift-snapshot-testingではrecursiveDescriptionでView階層をtextに出力できる ● recursiveDescriptionをもってレイアウト変更がないことの担保をする
swift-snapshot-testingのテストコード 0.9を指定10%差異があっても許容する
swift-snapshot-testingのテストコード View階層をTextファイルに出力
recursiveDescription textファイル
recursiveDescriptionの注意点 ● 実行端末によってレンダリング結果が異なる ○ 解像度、スクリーンサイズなどが影響 ● 実行端末を限定する必要がある
Snapshot Testingを 開発フローに導入しやすくする
テンプレートファイルを用意する
ViewControllerを作ればすぐに作成できる
まだ少し面倒?
Xcode Previews swift-snapshot-testing
まとめ ● メルペイのスナップショットテストでは複数端末での実行時間と画像出力が異なる問題があった ● swift-snapshot-testingを導入した ● 一度の実行で複数端末のキャプチャを撮影できるようになった ● 画像出力異なる問題は目視&View階層のText出力で担保 ● テンプレート作成でSnapshot Testingをやりやすくする