9
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

iOSでswift-snapshot-testingを使う

Last updated at Posted at 2019-10-06

swift-snapshot-testingとは

iOSのSnapShotテストといえばiOSSnapshotTestCaseが有名ですが、SnapshotTesting(swift-snapshot testing)というライブラリもあります。

この2つには大きな違いがあり、

iOSSnapshotTestCase swift-snapshot-testing
Objective-Cで書かれている Swiftで書かれている
対象はView 対象はViewに限らない

特に、『対象はViewに限らない』というところがポイントだと思います。
Snapshotの意味からすれば、こちらが普通ともいえますね。

とはいったものの、まずは画面のSnapshotを撮るために導入を検討するのでは?という観点からセットアップについて書いていきます。

サンプルプロジェクト
swift-snapshot-testing-sample

インストールする

READMEによると、Carthage / CocoaPods / Swift Package Managerに対応しています。

今回はCarthageでインストールする場合を紹介します。

Carthageインストール時のポイントは

  • テストターゲットのみに追加
  • 通常行うcopy-frameworksは行わない

になります。

つまり、テスト時のみ必要なライブラリですので、リリースビルドには含めないようにするということですね。

github "pointfreeco/swift-snapshot-testing" ~> 1.6

READMEの通りにセットアップを進めると、テストターゲットのBuild Phasesは、このようになります。
test_build_phases.png

XCodeを設定する

画像フォルダを設定

Snapshotテストが失敗した際に出力される画像を格納する、フォルダのパスを設定します。
この設定をしなくてもテストは可能なのですが、設定しないとファイルが出力されません。また、このフォルダは .gitignore に追加し、リポジトリには含めないようにしておきます。

edit_scheme2.png

SchemeのEnviroment Variablesに以下を追加します。

[Name] SNAPSHOT_ARTIFACTS

[Value] $(SOURCE_ROOT)/$(PROJECT_NAME)Tests/__Snapshots__/Failure

シミュレータ起動時の言語を設定

ローカル環境でSnapshotテストが通ったので、意気揚々とPushしたところ、CIでテストがコケるという現象が発生しました。CIから失敗時の画像をダウンロードして確認してみたところ、フォントが微妙に違っていました。
私の開発環境は日本語の設定ですが、CIではOSが素の状態でインストールされた状態なので、システムフォントが異なってしまうのが原因のようです。

シミュレータを日本語で起動することによって、解決できました。

edit_scheme1.png

SchemeのArguments Passed On Launchに以下を追加します。

-AppleLanguages (ja)

※アプリにより状況が異なると思いますので、必要に応じて対応してください

リファレンス画像を出力する

HomeSnapShotTests.swift
func testHomeViewController() {
    record = false
    
    let storyboard = UIStoryboard(name: "Home", bundle: nil)
    let vc = storyboard.instantiateInitialViewController()!
    
    SnapshotDevices.allCases.forEach {
        assertSnapshot(matching: vc, as: .image(on: $0.config), named: $0.name)
    }
}
record = true

にするとリファレンス画像が書き出されます。
また、場所の指定はできないようで、テストクラスと同じディレクトリに書き出されます。
project_dir.png
リファレンス画像の命名規則は、下記のようになります。

__Snapshots__/テストクラス名のフォルダ/テストケース名.{named:に渡した名前}.png

テストを実行する

ユニットテストの一環として実行されます。シミュレータの端末を選択し、コマンド+Uです。

READMEによると “単一のシミュレータからすべてのSnapshot画像を生成する” とのことなのですが、テスト時に選択された端末によって得られる画像が異なるようです。特にノッチのあり/なしで余白的な部分が変わりました。これは、リファレンス用のSnapshot画像を撮った端末とテスト時の端末が異なるとテストが失敗してしまうことを意味しています。
Snapshotテスト導入後は、ユニットテスト時の端末を統一するようにしました。
また、CIでのテストも、同じ端末を指定しておく必要があります。

画像のDiff

swift-snapshot-testingはテスト失敗時の差分画像を出力してくれません。
差分を比較したい場合は、Kaleidoscopeを使っています。2枚の画像を並べたり、重ねて違いを表示したりできます。

Two-Up Difference
スクリーンショット 2019-10-06 13.51.38.png スクリーンショット 2019-10-06 13.51.44.png

個人的には長年アプリケーションフォルダで眠っていたKaleidoscopeが、活躍する日が来てくれてうれしいです。

最後に

この記事のとおり導入はそれほど難しいものではありません。アプリをより良くしていこうとSnapshotテストの導入を検討している方々の参考になれば幸いです。

9
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?