iOS
objectivec
XCTest
screenshot
UITest

Objective-CでUITestを利用してスクリーンショットを撮る方法

概要

SwiftでUITestを利用してスクリーンショットを撮るサンプルは見つけられたが、Objective-Cの例が見つからなかったので、自分用に残しておく。

コードを書かずに自動でスクリーンショットを撮る方法

Objective-C関係なく、Xcodeの設定のみで可能。

Xcode-Scheme-Test-Setting.png

スキーマのTestの設定を開いて、チェックボックスを下記のようにする。

  • UI TestingのCapture screenshots automaticallyにチェックを入れる
    • 遷移した画面すべてを撮影してくれるようになる
  • UI TestingのDelete when eath test succeedsのチェックを外す
    • テスト成功時にスクリーンショットを削除しないようになる
  • AttachmentsのDelete when eath test succeedsのチェックを外す
    • テスト成功時にスクリーンショットを削除しないようになる

注意点としてものすごい量のスクリーンショットが作成されるので、必要のないもので必要なものが埋もれる可能性大。
管理が面倒臭い人は、任意の箇所で撮影する方法がいいかもしれない。

任意の箇所でスクリーンショットを撮る方法

2つの方法をあげているが、テスト完了後にレポートを見た際の見やすさが変わるだけなので、スクリーンショットを撮るコード自体は同じ。
用途に応じて選択すると吉。

シンプルにスクリーンショットを撮る方法

サンプル
- (void)testTakeScreenShot {
    XCUIApplication *app = [[XCUIApplication alloc] init];
    [app.buttons[@"ボタン"] tap];
    XCUIScreen *screen = [XCUIScreen mainScreen];
    // スクリーンショットを撮影
    XCUIScreenshot *screenShot = [screen screenshot];
    // アタッチメントを生成
    XCTAttachment *attachment = [XCTAttachment attachmentWithScreenshot:screenShot];
    // テスト実行後に削除しない
    attachment.lifetime = XCTAttachmentLifetimeKeepAlways;
    // スクリーンショットのファイル名のprefixに付加されるので設定しておくと楽
    attachment.name = @"tapped-button";
    [self addAttachment:attachment];
}

アクテビティを使ってログをグループ化する方法

サンプル
- (void)testTakeScreenShot {
    XCUIApplication *app = [[XCUIApplication alloc] init];
    [app.buttons[@"ボタン"] tap];
    [XCTContext runActivityNamed:@"ボタンをタップ" block:^(id<XCTActivity>  _Nonnull activity) {
        XCUIScreen *screen = [XCUIScreen mainScreen];
        XCUIScreenshot *screenShot = [screen screenshot];
        XCTAttachment *attachment = [XCTAttachment attachmentWithScreenshot:screenShot];
        attachment.lifetime = XCTAttachmentLifetimeKeepAlways;
        attachment.name = @"tapped-button";
        [activity addAttachment:attachment];
    }];
}

撮影後のスクリーンショットの保存場所

下記ディレクトリ内に保存される。

/Users/(UserName)/Library/Developer/Xcode/DerivedData/(Project)/Logs/Test/Attachments/

(2018/03/16 追記)スクリーンショットのファイル名をXcodeから指定したものにリネームする方法

保存されたスクリーンショットのファイル名は screen-shot-sample_1_7E21D0FF-5AAB-4318-81DA-034BABF95B01.png という感じになっている。
このファイル名を screen-shot-sample.png にリネームするコマンドがこちら。

コマンド
# スクリーンショットを格納したディレクトリの一つ上の階層で実行するコマンド
# イメージとしては、端末ごとに仕分けされたディレクトリ群を一気にリネームするときに使うもの
$ find ./ -type d | find ./ -type f | sed -E 'p;s/(.+)_[0-9]_.+\.png/\1.png/g' | xargs -n2 mv

# スクリーンショットを格納したディレクトリで実行するコマンド
$ find ./ -type f | sed -E 'p;s/(.+)_[0-9]_.+\.png/\1.png/g' | xargs -n2 mv

十数年ぶりにsedを使った…。

参考

Xcode 9からテストが大幅に進化します! - Timers Tech Blog
Hands-on XCUITest Features with Xcode 9
iOS 11 Programming