Page Object Pattern - アプリのUI変更に対応する
Page Object Pattern
というデザインパターンを使うとUI改修が起こることを含めた運用について改善することができる。
import XCTest import UIKit class LoginPage { // UI要素 private let emailTxtF: XCUIElement private let passwordTxtF: XCUIElement private let loginButton: XCUIElement init(_ app: XCUIApplication) { emailTxtF = app.textFields["email"] passwordTxtF = app.textFields["password"] loginButton = app.buttons["login_button"] } /// ログイン func login(email: String, password: String) { emailTxtF.tap() emailTxtF.typeText(email) passwordTxtF.tap() passwordTxtF.typeText(password) loginButton.tap() } }
Page Object Pattern では ページ1つにつきクラスを1つ用意。 各UI要素のプロパティは private
にして外部から直接参照できないようにする。
また、そのページに対して行う操作をメソッドにまとめて外部から呼び出せるようにする。
ただ、 必ずしもすべてのUI要素のプロパティを用意しておかなくてもよい。テストコード側で必要になったときに必要分だけ定義し、影響を最小限に留めるのが大切。
今回のサンプルコードではメソッドで遷移先を返していないが、返すか返さないかはどちらかを選ぶ。
Page Object Pattern のメリット
Accessibility Identifierが変更になったり部品が追加されたりした時に、Page Object Pattern を採用していると ページクラスの変更のみで対応ができ、テストケース側は修正する必要がない。
UI要素に対する複数の操作をまとめる
extension
で機能拡張を行い、よく使うメソッドをまとめるという手法も有効。
ただし、作る分学習コストが増えていくことは認識しておく必要がある。
import XCTest import UIKit class SampleTestCases: XCTestCase { func testInputText() { let app = XCUIApplication() let nicknameTxtF: XCUIElement = app.textFields["nickname"] nicknameTxtF.inputText("hoge") } } extension XCUIElement { func inputText(_ text: String) { tap() typeText(text) } }