LoginSignup
30
29

More than 5 years have passed since last update.

多言語対応。fastlane の snapshot で iOS アプリのスクリーンショットを自動的に作成する。 swiftで。

Last updated at Posted at 2015-12-26

iOS アプリのデリバリを自動的に行う、fastlane というフレームワークがあります。

AppStore への自動デプロイなど、超便利な機能がたくさんありますが、そのツール群の中に snapshot という、
iOS シミュレータを用いて、スナップショットを自動生成してくれるイカすツールでがあります。

その使い方を紹介します。

本記事の内容としては、公式リポジトリの README に書いてある内容そのままなので、そちらを見た方が確実ではあります。
https://github.com/fastlane/snapshot

動画撮りました: https://youtu.be/yBtb_jre1-I
(※ただの動作させてる動画です。説明とか無いです)

何ができるのか

高度なスクリーンショットの自動作成ができます。

マルチ画面サイズ対応

iPhone5, iPhone6, iPad など、画面サイズの違う各種デバイスを自動的に順番に起動し、スクリーンショットを撮影してくれます。

多言語対応

特に便利だと思ったのがコレ。多言語対応しているアプリの場合、シミュレータの言語を切り替えてスクリーンショットを撮影するのは面倒で骨の折れる作業ですが、snapshot ツールはそれも自動化してくれます。

処理の終了後には HTML ファイルを作って画像を一覧してくれるため、AppStore 提出用途だけでなく、多言語(かつ多画面サイズ)での表示確認用ツールとしてもすばらしく使い勝手が良いです。お昼休みに食事している間にスナップショットをひたすら作成させて、昼休み終わりにブラウザで確認。なんて使い方もできます。

UI自動操作テスト対応

スナップショットの撮影は、Xcode の UIテストフレームワークの中で行うため、UIテストの自動操作中のあるポイントでのスナップショットが柔軟に撮影できます。

インストール方法

snapshot 単体でのインストールもできると思いますが、fastlane ごとインストールするのが楽でしょう。

$ sudo gem install fastlane

アプリのプロジェクトルートで

$ fastlane init

設定ファイルの編集

fastlane/Snapfile ができるのでエディタで開きます。

devices, languages のリストを、用途に応じて編集します。

Snapfile
...
devices([
  "iPhone 6",
  "iPhone 5",
])

languages([
  "en-US",
  "ja-JP",
])
...

この場合、英語と日本語でスクリーンショットを、iPhone6 と iPhone5 シミュレータでそれぞれ撮影します。

出力ディレクトリの作成

デフォルトでは、fastlane/screenshots に保存しますが、自動的には作ってくれないため作っておきます。

$ mkdir fastlane/screenshots

テストフレームワークのセットアップ

UIテストの追加

プロジェクトの TARGETS に、UIテストを追加します。

Xcode の、TARGETS の + → iOS Testing Bundle → 適当に名前をつけて Finish.

ヘルパーファイルの追加

fastlane インストール時、 fastlane/SnapshotHelper.swift というファイルができているので、このファイルをマウスで Xcode の UIテストグループにドラッグ & ドロップします。
Add to targets: を聞かれるので、追加した UIテストにチェックが入っていることを確認し、Finish.

Objective-C の場合は、ヘッダファイルの用意など一手間必要なので、公式ページ参照。
https://github.com/fastlane/snapshot

UIテストコードの編集

UIテストコードを開き、setUp メソッドを編集します。

デフォルトで、XCUIApplication().launch() が入っていますが、これはコメントアウトし

        let app = XCUIApplication()
        setupSnapshot(app)
        app.launch()

こう変えます。

そして、testXXX などのテストメソッド中に、

snapshot("ファイル名")

を実行すれば、スナップショットが作られます。

コメントを抜いたUIテストコードは以下のようになります。

HogeUITests.swift

import XCTest

class YTempoIOSUiTests: XCTestCase {

    override func setUp() {
        super.setUp()
        continueAfterFailure = false
        let app = XCUIApplication()
        setupSnapshot(app)
        app.launch()
    }

    override func tearDown() {
        super.tearDown()
    }

    func testExample() {
        snapshot("01-main-screen")
    }
}

この場合は、起動直後のスクリーンショットだけを保存します。

自動操作を行うには、このファイルの場合 testExample メソッドにカーソルを置き、左下の録画ボタンをクリック。

シミュレータが起動するので、操作すると操作内容がコードとして記録されます。

スクリーンショットを記録したいタイミングで snapshot 関数を呼ぶことで、自動的にスナップショットが作られます。いいね!

実行

デフォルトでは、fastlane の各レーンに組み込まれているため、

$ fastlane test

でも起動できますし、snapshot コマンド単体で起動することもできます。

$ snapshot

作成されたHTML

スクリーンショット 2015-12-26 18.40.59.png

課題

多言語化している場合、UIテストで

UITest.swift
let app = XCUIApplication()
app.buttons["English message"].tap()

このようなコードになっていると、English message が日本語に翻訳されている場合ボタンが見つからずに押せなくなります。

XCUIElement.exists プロパティで、エレメントの存在テストができるため

UITest.swift
        let buttonLabels = [
            ["+ 1 BPM every 20 beats from 70 BPM", "Set"],
            ["20拍ごとに +1BPM、70BPM開始", "セット"],
        ]
        for labels in buttonLabels {
            if (app.buttons[labels[0]].exists){
                app.buttons[labels[0]].tap()
                snapshot("02-trainer-settings")
                app.buttons[labels[1]].tap()
                break
            }
        }

一応こんな感じで分岐はできますが…なんか他に良い方法ないですかね。

テストコード内で、ボタン名の判定を下記のようにNSLocalizedString にしても、OSの言語設定を評価してくれるわけではないので、ボタンを見つけられず失敗しました。

失敗コード
app.buttons[NSLocalizedString("Set", comment: "")].tap()

30
29
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
30
29