最近テスト書かなきゃという謎の焦燥感が高まっております🔥
そんな折iOSSnapshotTestCaseなるものの存在を知ったので使い方をまとめます✊
iOSSnapshotTestCaseとは
https://github.com/uber/ios-snapshot-test-case
テスト対象のUIView
またはCALayer
のスナップショットを撮り、あらかじめ用意しておいた参考画像と比較し、一致するか確認するテスティングフレームワークです。
参考画像を生成することもできるので、必ずしも事前に参考画像を用意する必要はありません。
これを使うことで、いろんなパターンのビューの画像を生成したり、リグレッションテストを実施することができます。
使い方
インストール
CocoaPodsでインストールできます。
テストのターゲットにiOSSnapshotTestCase
を追加します。
target "プロジェクトTests" do
use_frameworks!
pod 'iOSSnapshotTestCase'
end
画像の置き場を設定
比較あるいは生成した参考画像、テストが失敗したときの画像を置く場所を設定します。
いつくか方法があるみたいですが、READMEに載っているやり方だとSchemeの環境変数に以下を定義してやります。
もしディレクトリのパスやターゲットの名前を変更している場合は、適宜合わせてください。
ディレクトリが存在しない場合は勝手に生成してくれるので、事前に作っておく必要はありません。
name | value |
---|---|
FB_REFERENCE_IMAGE_DIR |
$(SOURCE_ROOT)/$(PROJECT_NAME)Tests/ReferenceImages |
IMAGE_DIFF_DIR |
$(SOURCE_ROOT)/$(PROJECT_NAME)Tests/FailureDiffs |
RunのArgumentsにあるEnvironment Variablesに書きます。
Testじゃなくていいの?と思われるかもしれませんが、デフォルトでRunの設定を引き継ぐようになっているようです。もちろんチェックを外してTestだけに書いてもらっても構わないと思います。
テスト記述
クラス定義
FBSnapshotTestCase
を継承したクラスを定義します。FBSnapshotTestCase
はXCTestCase
のサブクラスです。
import XCTest
import FBSnapshotTestCase
@testable import SwiftTest // 適宜プロジェクトに合わせて置き換える
class SomeViewTests: FBSnapshotTestCase {
...
setup
setUp()
でrecordMode
の設定をします。参考画像を生成したい場合はtrue
、既にある参考画像と比較を行う場合はfalse
を入れます。
...
class SomeViewTests: FBSnapshotTestCase {
override func setUp() {
super.setUp()
self.recordMode = false // or true
}
...
テストケース
XCTestCase
と同様にtest
で始まるメソッドを書いていきます。画像の比較または参考画像の生成にはFBSnapshotVerifyView()
を使います。
...
func testRed() {
let view = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 60))
view.backgroundColor = .red // テストしたい状態にする
FBSnapshotVerifyView(view) // 比較 or 参考画像生成
}
func testBlue() {
let view = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 60))
view.backgroundColor = .blue // テストしたい状態にする
FBSnapshotVerifyView(view) // 比較 or 参考画像生成
}
...
使用上の注意
シミュレータでないとテストできない
実機を選んだ状態でテストすると、参考画像が見つからない的なエラーでfailします。
テスト実行時はシミュレータを選択した状態にしておきましょう。
サイズが(0, 0)のビューは画像が生成されない
考えてみれば当たり前ですが、recordMode
をtrue
にして参考画像を生成する際に、ビューのサイズが(0, 0)だと画像が生成されません。ただし、テストfailのメッセージには画像を生成した旨が表示されます。
参考画像が格納されるディレクトリも生成されないので、一番最初に実行する際には注意が必要です。
使ってみて思ったこと
動作確認にとても良い
従来はアプリを起動して目的の画面に行って目的のビューを見る、ということをデータのパターン分繰り返していました。それがiOSSnapshotTestCaseを使えば、必要なデータだけ用意してrecordMode = true
でテストを実行すれば画像を生成してくれるので、複数パターンあるビューや複数端末サイズでの動作確認がとても楽になりました。
テストの知識がそんなにいらないので楽
モックを作って置き換えてみたいなことは一切せず、ビュー作るだけでいいので、テストに不慣れな人でもすぐ取り組むことができます。
画像の容量が際限なく増えていくのが若干不安
いろんなパターンでビューの画像を取りまくるので、容量もどんどん増えていきます。CIでgit clone
するときに遅くなってしまわないか不安はあります。
おわりに
テストというと難しいもの、というイメージがどうしてもありますが、iOSSnapshotTestCaseを使ったテストは非常に簡単です
これを足がかりにテストを書きはじめて、iOSSnapshotTestCaseでカバーできない部分があることを知り、モックなどを使う次のステップへ、という風な流れを作りやすいんじゃないでしょうか
どんどんテスト書いていきましょう!