アイキャッチ画像は acworksさんによる写真ACからの写真 を利用しています。
MacアプリのUIテストで、ダイアログのテスト方法についてです。
ダイアログの表示待機
何かボタンをクリックしたら表示されるダイアログ、アプリ起動時に表示されるダイアログ、メニューからコマンドを実行すると表示されるダイアログなど、色々な方法でダイアログは表示されます。しかし、どの方法であっても共通するのは、表示されるまで待機するということです。
マシンスペックやマシンの状態などによって、どのくらいのタイミングでダイアログが表示できるかというのは微妙に異なります。それらに依存せずにダイアログが表示されるまで待機すると同時にダイアログが表示されることをテストするには、次のようにします。
let app = XCUIApplication()
// "alert_window"という識別子のダイアログの表示待機
let alertDialog = app.dialogs["alert_window"]
XCTAssertTrue(alertDialog.waitForExistence(timeout: 5))
タイムアウトの5秒は、そこまでかかることはないという値です。
“dialogs”と”windows”のどちらを使うか
XCTestでウインドウを取得するときに、「dialogs」を使うか「windows」を使うかは、取得対象のウインドウのイベント処理の方法で決まります。
次のようにモーダルダイアログとして使っているときは「dialogs」です。ドキュメントウインドウなど、ウインドウを表示しているだけで、モーダルセッションを使っていないときは「windows」です。
NSApplication.shared.runModal(for: alert.window!)
共通ダイアログクラスが連続するとき
共通のダイアログクラス、例えば、アラートメッセージ用のクラスなど、識別子が同じダイアログが連続して表示されるみたいなときには、スリープを入れると判定できます。
次のコードは、最初のアラートで「削除しても良いですか?」と確認しています。「OK」ボタンがクリックされたら、「ロックされている項目があります。強制的に削除しますか?」と表示されるかをテストしているコードです。文字列はLocalizable.stringsから取得しています。
let app = XCUIApplication()
var bundle = Bundle(for: type(of: self))
XCTContext.runActivity(named: "1st alert") { (activity) -> Void in
// "alert_window"という識別子のダイアログの表示待機
let alertDialog = app.dialogs["alert_window"]
XCTAssertTrue(alertDialog.waitForExistence(timeout: 5))
// "message_label"の取得と存在チェック
let label = alertDialog.staticTexts["message_label"]
XCTAssertTrue(label.exists)
// メッセージの表示内容をチェック
XCTAssertEqual(label.value as? String,
bundle.localizedString(forKey: "ConfirmDelete", value: nil, table: nil))
// OKボタンの取得と存在チェック
let okButton = alertDialog.buttons["ok_button"]
XCTAssertTrue(okButton.exists)
// OKボタンをクリック
okButton.click()
}
// アラートが閉じて、別のアラートが表示されるので、1秒待つ
Thread.sleep(forTimeInterval: 1)
XCTContext.runActivity(named: "2nd alert") { (activity) -> Void in
// "alert_window"という識別子のダイアログの表示待機
let alertDialog = app.dialogs["alert_window"]
XCTAssertTrue(alertDialog.waitForExistence(timeout: 5))
// "message_label"の取得と存在チェック
let label = alertDialog.staticTexts["message_label"]
XCTAssertTrue(label.exists)
// メッセージの表示内容をチェック
XCTAssertEqual(label.value as? String,
bundle.localizedString(forKey: "ItemIsLocked_ConfirmDeleteForce", value: nil, table: nil))
// OKボタンの取得と存在チェック
let okButton = alertDialog.buttons["ok_button"]
XCTAssertTrue(okButton.exists)
// OKボタンをクリック
okButton.click()
}