wide and shallow life.

四十路アプリ開発者の備忘録

fastlane/snapshotでアプリのスクショをバシャバシャ撮ろう。

はるそうパパです。今日はぬくい!春一番です!

さて、本日ご紹介するのはXcodeのUITestを利用してアプリのスクショが自動で撮れる「fastlane/snapshot」です。
iOSアプリの新規申請を行う際にとにかく面倒なのがスクショをたくさん撮らねばならないことです。
例えば、3画面分で日英対応しているアプリですと端末数が3.5インチ、4インチ、4.7インチ、5.5インチ、iPadと5種類分ありますので、3 × 2 × 5 = 30枚ものスクショが必要となります。

私も今まで手動でこれらの苦行を行っていたのですが、「fastlane/snapshot」を導入することで自動化され苦行から解放されるのです!

fastlane/snapshotのインストール

では早速公式サイトを参考にインストールから行いましょう!
github.com

$ sudo gem install snapshot

Rubyのバージョが低いと怒られるかもしれませんので、その時は先にRubyのバージョンをあげましょう。

$ xcode-select --install

Xcodeのcommand line toolsも最新にしてください。すでにインストール済みですと怒られますw

xcode-select: error: command line tools are already installed, use "Software Update" to install updates
XcodeプロジェクトファイルにUITestを追加

fastlane/snapshotで指定の画面を表示するためにXcodeの標準UIテストを利用します。

今回はすでに下記のようなObjective-Cのプロジェクトが存在する前提で進めます。(全ソースはこちらをご参照ください)

【検証環境】

Xcodeバージョン 7.2
プロジェクト内容 Master-Detail
プロジェクト名 HSASnapshot
UITestターゲット名 HSASnapshotUITests
UITestスキーマ HSASnapshotUITests
  1. Xcodeのメニューから「File」->「New」->「Target」を選択します。
  2. 開いたダイアログの左ペインで「iOS」の「Test」を選択し、右側の「iOS UI Testing Bundle」を選択し、「Next」ボタンを押します。
  3. オプション入力画面が表示されますので、基本そのままで「Finish」ボタンを押してください。

f:id:yokada3:20160213174338p:plain

fastlane/snapshotの初期化

Xcodeでテスト用ターゲットを用意できましたら、fastlane/snapshotの初期化を行います。

  1. ターミナルを開き、対象のXcodeプロジェクトまで移動します。
  2. そこで下記コマンドでfastlane/snapshotの初期化をします。
  3. 初期化が成功しますとXcodeプロジェクトと同じ階層に「Snapfile」と「SnapshotHelper.swift」が作られます。
$ snapshot init

f:id:yokada3:20160213181928p:plain

SnapshotHelper.swiftの追加
  1. Xcodeを開きテストターゲットに「SnapshotHelper.swift」を追加します。
  2. Objective-Cswiftのブリッジヘッダーが必要ですので、ダイアログでは「Create Bridging Header」を選択します。

f:id:yokada3:20160213183112p:plain
f:id:yokada3:20160213183430p:plain

テスト用のスキーマを作成

次にXcodeでUIテストを行う必要がありますので、テスト用スキーマを作ります。

  1. Xcodeのメニューから「Product」->「Scheme」->「New Scheme...」を選択します。
  2. Targetを先ほど作成したUITest用のターゲットに変更し、「OK」ボタンを押します。

f:id:yokada3:20160213184553p:plain

さらにテストスキーマでアプリが実行できるようにします。(これを行わないと最後のsnapshot実行時にエラーとなります)

  1. スキーマを「HSASnapshotUITests」に切り替えます。
  2. スキーマをクリックしてメニューの「Edit scheme...」を選択します。
  3. Runのexecutableを「None」から選択可能なappに変更し、Closeします。

f:id:yokada3:20160213212501p:plain

画面遷移とスクショを撮るためのコーディングを行う

プロジェクト作成を「Master-Detail Application」で行いましたので、今回は下記動作を行うテストコードを書きます。

  1. 画面起動後+ボタンを押す
  2. 1秒待つ
  3. スクリーンショットを撮る
  4. テーブルの一番目のセルをタップ
  5. 1秒待つ
  6. スクリーンショットを撮る

UITestクラスの「setup」メソッドと「testExample」メソッドにコードを追加します。

- (void)setUp {
    [super setUp];
    
    // Put setup code here. This method is called before the invocation of each test method in the class.
    
    // In UI tests it is usually best to stop immediately when a failure occurs.
    self.continueAfterFailure = NO;
    // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
    XCUIApplication *app = [[XCUIApplication alloc] init];
    [Snapshot setLanguage:app];
    [app launch];
    
    // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
}
- (void)testExample {
    // Use recording to get started writing UI tests.
    // Use XCTAssert and related functions to verify your tests produce the correct results.
    XCUIApplication *app = [[XCUIApplication alloc] init];
    
    //Tap Navifation Rght (+) Button
    [[app.navigationBars[@"Master"].buttons elementBoundByIndex:2] tap];
    
    sleep(1);
    [Snapshot snapshot:@"master" waitForLoadingIndicator:YES];
    
    [[app.tables.cells elementBoundByIndex:0] tap];
    sleep(1);
    [Snapshot snapshot:@"detail" waitForLoadingIndicator:YES];

}
Snapshotクラスでエラーにならないようにする!

今回のキモです。といいますか、私はここで躓きました。先ほどのコードをコピペしてビルドすると三箇所でエラーとなります。
それは「[Snapshot・・・」の部分です。
ここで一度お手間ですが、エラー部分をコメントアウトしてビルドエラーを解消します。
その上で、テスト用のビルドを行い、自動生成されたヘッダーファイルをimportすることでエラーが解消します。

  1. スキーマをUIテスト用スキーマに変更します。(HSASnapshotUITests)
  2. Xcodeのメニューから「Product」->「Build For」->「Testing」を選択します。
  3. ビルド完了まで待ちます!
  4. ビルド完了後、テストクラスにimportを追加します。(名称はターゲット-Swift.hと読み替えてください。コード補完はされません。)
  5. 先ほどエラーとなったSnapshotクラスの呼び出し部分のコメントを戻します。
  6. 再度ビルドしてもエラーとならないことを確認します。
#import "HSASnapshotUITests-Swift.h"
Snapfileの編集

長かった戦いがもうすぐ終わります。。
最後にSnapfileを適宜書き換えて「snapshot」コマンドを叩くだけです!
Xcodeプロジェクト直下にあるSnapfileをテキストエディターで修正します。
今回はiPhone5で日英のスクリーンショットを出力するようにしました。

# Uncomment the lines below you want to change by removing the # in the beginning

# A list of devices you want to take the screenshots from
devices([
#   "iPhone 6",
#   "iPhone 6 Plus",
     "iPhone 5",
#   "iPhone 4s",
#   "iPad Retina",
#   "iPad Pro"
])

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

# Arguments to pass to the app on launch. See https://github.com/fastlane/snapshot#launch-arguments
# launch_arguments("-favColor red")

# The name of the scheme which contains the UI Tests
scheme "HSASnapshotUITests"

# Where should the resulting screenshots be stored?
output_directory "./screenshots"

clear_previous_screenshots true # remove the '#' to clear all previously generated screenshots before creating new ones

# Choose which project/workspace to use
project "./HSASnapshot.xcodeproj"
# workspace "./Project.xcworkspace"

# For more information about all available options run
# snapshot --help
よろしくお願いしまぁぁぁぁぁぁすぅぅぅ!
$ snapshot

いよいよスクリーンショット自動取得!です。威勢よくエンターキーを押しましょう。

最後に下記画像がでれば完了です。成功していればグリーンのハートが出て失敗すると赤バツです。
f:id:yokada3:20160213194606p:plain

自動的にHTMLファイルも生成してくれるので画面崩れのチェックなど端末ごとのデザインチェックにも最適です。
↓こんな感じに出力結果が確認できます。
f:id:yokada3:20160213210707p:plain

本エントリが皆さまの自動化ライフのお役に立てたら幸いです♪

そして、自動化戦士の戦いは続く・・・(deliver編に続く。。かも)