LoginSignup
1
0

More than 5 years have passed since last update.

iOSSnapshotTestCaseでスナップショットテストを行う実装のサンプル

Last updated at Posted at 2019-04-17

iOSSnapshotTestCaseを使用してスナップショットテストを行う際の大まかな実装についての個人的なまとめ

iOSSnapshotTestCase: https://github.com/uber/ios-snapshot-test-case

前置き

スナップショットテストはViewのテストであり、ロジックのテストでは無い
ロジックはロジックでテストを実装すること

スナップショットテストの目的

Viewのリグレッションテストを全て人間がやるのは辛いので、ある程度の自動化を図る

実装

言語デバイスの組み合わせ毎のスナップショットテストを行うサンプル
テストクラスの外で実装したfunctionの挙動についてはソースコメント参照

import FBSnapshotTestCase
@testable import SnapShotTestExample

class FBSnapshotTestCaseSwiftTest: TestCase {
    private let baseball = Sample.baseball
        |> Sample.lens.state .~ .successful // テスト用のtemplateデータをテストケースに合わせて再作成する(state = .successful)
    private let yamada = User.yamada
    private let xxx = Xxx.template

    override func setUp() {
        super.setUp()
        UIView.setAnimationsEnabled(false)
//        recordMode = true
    }

    override func tearDown() {
        UIView.setAnimationsEnabled(true)
        super.tearDown()
    }

    func testXxx() {
        // Mockを用意する
        let service = MockService(fetchXxxResponce: self.xxx)

        // LanguageとDeviceの組み合わせのタプルを回す
        combos(Language.allCases, [Device.phone4_7inch, Device.phone5_8inch, Device.pad]).forEach {
            language, device in
            withEnvironment( // テスト用の一時的な環境を作ってテストを実行する
                apiService: service,
                language: language
            ) {
                let controller = SampleViewController.configuredWith(sample: self.baseball, user: self.yamada)

                // 指定した `デバイス(サイズ)` と `向き` のviewcontrollerを作る
                let (parent, _) = traitControllers(device: device, orientation: .portrait, child: controller)

                // スナップショットテスト
                FBSnapshotVerifyView(parent.view, identifier: "lang_\(language)_device_\(device)")
            }
        }
    }

    func testXxx_Canceled() {
        // テスト用のtemplateデータをテストケースに合わせて再作成する(status = .canceled)
        let xxxCanceled = .template |> Xxx.lens.status .~ .canceled
        let service = MockService(fetchXxxResponce: xxxCanceled)

        combos(Language.allCases, [Device.phone4_7inch, Device.phone5_8inch, Device.pad]).forEach {
            language, device in
            withEnvironment(
                apiService: service,
                language: language
            ) {
                let controller = SampleViewController.configuredWith(sample: self.baseball, user: self.yamada)
                let (parent, _) = traitControllers(device: device, orientation: .portrait, child: controller)

                FBSnapshotVerifyView(parent.view, identifier: "lang_\(language)_device_\(device)")
            }
        }
    }
}
extension Sample {
    internal static let template = Sample(
        id: 1,
        name: "Sample",
        state: .live
    )

    // 代表的なテストデータtemplateを定義する(id = 50, name = "Baseball")
    internal static let baseball = .template
        |> Sample.lens.id .~ 50
        |> Sample.lens.name .~ "Baseball"
}

最後に

makefileなどを使ってコマンドでテストを実行できるようにすると良い

1
0
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
1
0