LoginSignup
4
3

More than 3 years have passed since last update.

[iOS 14] XCUITestでアプリを削除する

Last updated at Posted at 2021-03-03

アプリの初回起動時のみに表示される画面をテストする必要があったので、 XCUITest でアプリを削除する方法について調べました。

WEB上にいくつか参考になる記事がありましたが、iOS 14のアプリ削除フローに対応した実装方法が見当たらなかったので内容をまとめてみました。

iOS 14でのアプリ削除フロー

iOS 14では以下のようにアプリを削除します

アプリアイコン長押し コンテキストメニュー 削除確認アラート1 削除確認アラート2
Simulator Screen Shot - iPhone 11 Pro - 2021-03-03 at 15.05.15.png Simulator Screen Shot - iPhone 11 Pro - 2021-03-03 at 15.05.19.png Simulator Screen Shot - iPhone 11 Pro - 2021-03-03 at 15.05.23.png Simulator Screen Shot - iPhone 11 Pro - 2021-03-03 at 15.05.27.png
ホーム画面上で
削除するアプリのアイコンを長押し
コンテキストメニューで
アプリの削除を選択
ホーム画面からの削除確認アラートで
アプリの削除を選択
アプリ削除確認アラートで
アプリの削除を選択

ポイントは、アプリを削除(アンインストール)するための確認アラート(上記の 削除確認アラート2 )が表示される前に、アプリの情報を保持しつつホーム画面から削除するための確認アラート(上記の 削除確認アラート1 )が表示される点です。

なお、コンテキストメニューが表示されてもアプリアイコンの長押しをしたままにすると、各アプリアイコンの左上に削除を示すマイナス:no_entry:ボタンが表示されますが、このフローだと上手く削除できない場合があることが分かったので、今回はコンテキストメニューでアプリの削除を選択するフローを採用しました。

実装

上記を踏まえて、アプリを削除するプログラムを書いていきましょう。
今回は SpringBoard 1 を使ってアプリの削除フローをSwiftで記述します。

struct Springboard {
    private static let myAppName = "削除するアプリ名"
    private static let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")

    static func deleteApp(name: String = myAppName) {
        XCUIApplication().terminate()

        springboard.activate()

        XCUIDevice.shared.orientation = UIDeviceOrientation.portrait
        Thread.sleep(forTimeInterval: 2.0)

        let appIcon = springboard.icons[name]
        guard appIcon.exists else {
            return
        }
        appIcon.press(forDuration: 1.5)

        let preferredLanguageCode = NSLocale.preferredLanguages[0].prefix(2)

        // コンテキストメニュー
        let firstDeleteButtonText = preferredLanguageCode == "ja" ? "Appを削除" : "Remove App"
        springboard.buttons[firstDeleteButtonText].firstMatch.tap()
        Thread.sleep(forTimeInterval: 1.0)

        // 削除確認アラート1
        let secondDeleteButtonText = preferredLanguageCode == "ja" ? "Appを削除" : "Delete App"
        springboard.buttons[secondDeleteButtonText].firstMatch.tap()
        Thread.sleep(forTimeInterval: 1.0)

        // 削除確認アラート2
        let thirdDeleteButtonText = preferredLanguageCode == "ja" ? "削除" : "Delete"
        springboard.buttons[thirdDeleteButtonText].firstMatch.tap()

        Thread.sleep(forTimeInterval: 0.5)

        XCUIDevice.shared.press(.home)
    }
}

確認アラートの文言などはシミュレーターの言語設定によって変わるので、必要に応じて切り分けます。
英語の RemoveDelete で表記ゆれしているのは地味にハマりどころかもしれません :sweat_smile:

これをUIテストのアプリ起動前に呼び出せば、毎回クリーンな状態でテストを実行できます :tada:

import XCTest

class MyAppUITests: XCTestCase {
    override func setUp() {
        super.setUp()

        // In UI tests it is usually best to stop immediately when a failure occurs.
        continueAfterFailure = false

        // インスタンスメソッド `setUp()` で呼び出せば、各テストメソッドの実行前にアプリが削除される
        Springboard.deleteApp()

        // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
        XCUIApplication().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.
    }

...

}

別フロー

コンテキストメニューでアプリの削除を選択せずにアプリアイコンを長押ししつづけていると、アプリアイコンたちがプルプルしはじめ、各アプリアイコンの左上には削除を示すマイナス:no_entry:ボタンが表示されます。

このフローでもアプリを削除できますが、環境やタイミングによっては想定外のアラートなどに邪魔されてしまうことがありました。

アプリアイコン長押し継続 確認アラート 想定外のアラート
コンテキストメニューが表示されても
無視して押し続ける
削除確認アラートが表示されることもあるが ホーム画面編集についてのお知らせアラートなどに
邪魔されてしまうこともある

もちろんこれらを適切にハンドリングできればテストは可能だと思いますが、今回は採用を見送りました。

参考

XCUITestでアプリを削除する


  1. iOSのホーム画面やそれに付随した機能を管理するためのソフトウェア 

4
3
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
4
3