} } }

次に、テキストフィールドのデリゲートメソッドを追加して、テキストフィールドのいずれかがいつ更新されているかを追跡します。

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { guard let viewModel = viewModel else { return true } let newString = (textField.text! as NSString).replacingCharacters(in: range, with: string) switch textField.tag { case TextFieldTags.emailTextField: viewModel.emailAddress = newString case TextFieldTags.passwordTextField: viewModel.password = newString case TextFieldTags.confirmPasswordTextField: viewModel.passwordConfirmation = newString default: break } return true }
  1. 更新AppDelegateビューコントローラを適切なビューモデルにバインドします(この手順はMVVMアーキテクチャの要件であることに注意してください)。更新されたAppDelegateコードは次のようになります。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { initializeStartingView() return true } fileprivate func initializeStartingView() { if let rootViewController = window?.rootViewController as? RegistrationViewController { let networkService = NetworkServiceImpl() let viewModel = RegisterationViewModel(networkService: networkService) rootViewController.viewModel = viewModel } }

ストーリーボードファイルとRegistrationViewControllerは本当にシンプルですが、自動化されたUIテストがどのように機能するかを示すには十分です。

すべてが正しく設定されている場合は、アプリの起動時に登録ボタンを無効にする必要があります。すべてのフィールドが入力されて有効な場合にのみ、登録ボタンを有効にする必要があります。

これを設定したら、最初のUIテストを作成できます。

UIテストでは、有効な電子メールアドレス、有効なパスワード、および有効なパスワードの確認がすべて入力された場合にのみ、[登録]ボタンが有効になるかどうかを確認する必要があります。これを設定する方法は次のとおりです。

  1. TestingIOSUITests.swiftを開きますファイル。
  2. testExample()を削除しますメソッドを追加し、testRegistrationButtonEnabled()を追加します方法。
  3. testRegistrationButtonEnabledにカーソルを置きますあなたがそこに何かを書くつもりのような方法。
  4. UIテストの記録ボタン(画面下部の赤い丸)を押します。

画像:[UIテストの記録]ボタンを示すスクリーンショット。

  1. 録音ボタンを押すと、アプリケーションが起動します
  2. アプリケーションが起動したら、メールテキストフィールドをタップして「 [メール保護] ’。コードがテストメソッド本体内に自動的に表示されていることがわかります。

この機能を使用してすべてのUI命令を記録できますが、簡単な命令を手動で作成する方がはるかに高速である場合があります。

これは、パスワードのテキストフィールドをタップしてメールアドレスを入力するためのレコーダーの指示の例です。 [メール保護] '

let emailTextField = XCUIApplication().otherElements.containing(.staticText, identifier:'Email Address').children(matching: .textField).element emailTextField.tap() emailTextField.typeText(' [email protected] ')
  1. テストするUIインタラクションが記録されたら、停止ボタンをもう一度押して(記録を開始すると、記録ボタンのラベルが停止に変更されました)、記録を停止します。
  2. UIインタラクションレコーダーを入手したら、さまざまなXCTAssertsを追加できます。アプリケーションまたはUI要素のさまざまな状態をテストします。

画像:パスワードフィールドをタップするためのレコーダーの指示を示すアニメーション。

記録された指示は必ずしも自明であるとは限らず、テスト方法全体を読みにくく、理解しにくくすることさえあります。幸い、UI命令を手動で入力できます。

次のUI命令を手動で作成しましょう。

  1. ユーザーはパスワードテキストフィールドをタップします。
  2. ユーザーが「パスワード」を入力します。

UI要素を参照するには、プレースホルダー識別子を使用できます。プレースホルダー識別子は、ストーリーボードの[ユーザー補助]の下の[IDインスペクター]ペインで設定できます。パスワードテキストフィールドのユーザー補助識別子を「passwordTextField」に設定します。

パスワードUIインタラクションは、次のように記述できます。

let passwordTextField = XCUIApplication().secureTextFields['passwordTextField'] passwordTextField.tap() passwordTextField.typeText('password')

UIインタラクションがもう1つ残っています。それは、パスワード入力の確認インタラクションです。今回は、プレースホルダーでパスワードの確認テキストフィールドを参照します。ストーリーボードに移動し、パスワードの確認テキストフィールドに「パスワードの確認」プレースホルダーを追加します。これで、ユーザーインタラクションは次のように記述できます。

let confirmPasswordTextField = XCUIApplication().secureTextFields['Confirm Password'] confirmPasswordTextField.tap() confirmPasswordTextField.typeText('password')

これで、必要なUIインタラクションがすべて揃ったら、あとは簡単なXCTAssertを書くだけです。 (単体テストで行ったのと同じ)[登録]ボタンのisEnabledかどうかを確認します状態はtrueに設定されます。登録ボタンは、そのタイトルを使用して参照できます。ボタンのisEnabledを確認するためにアサートしますプロパティは次のようになります。

let registerButton = XCUIApplication().buttons['REGISTER'] XCTAssert(registerButton.isEnabled == true, 'Registration button should be enabled')

UIテスト全体は次のようになります。

func testRegistrationButtonEnabled() { // Recorded by Xcode let emailTextField = XCUIApplication().otherElements.containing(.staticText, identifier:'Email Address').children(matching: .textField).element emailTextField.tap() emailTextField.typeText(' [email protected] ') // Queried by accessibility identifier let passwordTextField = XCUIApplication().secureTextFields['passwordTextField'] passwordTextField.tap() passwordTextField.typeText('password') // Queried by placeholder text let confirmPasswordTextField = XCUIApplication().secureTextFields['Confirm Password'] confirmPasswordTextField.tap() confirmPasswordTextField.typeText('password') let registerButton = XCUIApplication().buttons['REGISTER'] XCTAssert(registerButton.isEnabled == true, 'Registration button should be enabled') }

テストが実行されると、Xcodeはシミュレーターを起動し、テストアプリケーションを起動します。アプリケーションが起動した後、UIインタラクション命令が1つずつ実行され、最後にアサートが正常にアサートされます。

テストを改善するために、isEnabledもテストしてみましょう。必須フィールドのいずれかが正しく入力されていない場合、登録ボタンのプロパティはfalseです。

完全なテストメソッドは次のようになります。

func testRegistrationButtonEnabled() { let registerButton = XCUIApplication().buttons['REGISTER'] XCTAssert(registerButton.isEnabled == false, 'Registration button should be disabled') // Recorded by Xcode let emailTextField = XCUIApplication().otherElements.containing(.staticText, identifier:'Email Address').children(matching: .textField).element emailTextField.tap() emailTextField.typeText(' [email protected] ') XCTAssert(registerButton.isEnabled == false, 'Registration button should be disabled') // Queried by accessibility identifier let passwordTextField = XCUIApplication().secureTextFields['passwordTextField'] passwordTextField.tap() passwordTextField.typeText('password') XCTAssert(registerButton.isEnabled == false, 'Registration button should be disabled') // Queried by placeholder text let confirmPasswordTextField = XCUIApplication().secureTextFields['Confirm Password'] confirmPasswordTextField.tap() confirmPasswordTextField.typeText('pass') XCTAssert(registerButton.isEnabled == false, 'Registration button should be disabled') confirmPasswordTextField.typeText('word') // the whole confirm password word will now be 'password' XCTAssert(registerButton.isEnabled == true, 'Registration button should be enabled') }

ヒント:UI要素を識別するための推奨される方法は、アクセシビリティ識別子を使用することです。名前、プレースホルダー、またはローカライズ可能なその他のプロパティが使用されている場合、別の言語が使用されていると要素は見つかりません。その場合、テストは失敗します。

UIテストの例は非常に単純ですが、自動化されたUIテストの威力を示しています。

Xcodeに含まれているUIテストフレームワークのすべての可能性(および多くの可能性)を発見する最良の方法は、プロジェクトでUIテストの作成を開始することです。示されているような単純なユーザーストーリーから始めて、ゆっくりとより複雑なストーリーとテストに移ります。

良いテストを書いてより良い開発者になる

私の経験から、良いテストを学び、書き込もうとすると、開発の他の側面について考えるようになります。それはあなたがより良くなるのを助けます iOS開発者 完全に。

総アドレス可能市場とは何ですか

優れたテストを作成するには、コードをより適切に整理する方法を学ぶ必要があります。

組織化されたモジュール式の適切に記述されたコードは、ストレスのないユニットおよびUIテストを成功させるための主な要件です。

場合によっては、コードが適切に編成されていないと、テストを作成できないことさえあります。

アプリケーションの構造とコードの編成について考えると、MVVM、MVP、VIPER、またはその他のそのようなパターンを使用することで、コードがより適切に構造化され、モジュール化され、テストが容易になることがわかります(Massive View Controllerの問題も回避できます)。 。

テストを作成するときは、間違いなく、ある時点で、モッククラスを作成する必要があります。依存性注入の原則とプロトコル指向のコーディング手法について考え、学ぶことができます。これらの原則を理解して使用することで、将来のプロジェクトのコード品質が大幅に向上します。

テストを書き始めると、コードを書くときにコーナーケースとエッジ条件についてもっと考えていることに気付くでしょう。これは、バグになる前に起こりうるバグを排除するのに役立ちます。メソッドの考えられる問題とネガティブな結果について考えると、ポジティブな結果をテストするだけでなく、ネガティブな結果もテストし始めます。

ご覧のとおり、単体テストはさまざまな開発の側面に影響を与える可能性があり、優れた単体テストとUIテストを作成することで、より優れた幸せな開発者になる可能性があります(バグの修正に多くの時間を費やす必要はありません)。

自動テストの作成を開始すると、最終的には自動テストのメリットがわかります。あなたがそれを自分で見るとき、あなたはその最強の支持者になるでしょう。