1つの入力フィールドと送信ボタンのある小さなフォームのページがあります。送信ボタンはAJAXです!クリックすると、入力値がサーバーに送信され、サーバーはそれを受け入れ可能であると検証して新しいページをロードするか、問題を見つけてフィードバックエラーラベルを追加します。
この機能をテストするために、次のセレンコードを作成しました。
WebDriverWait waiter = new WebDriverWait(driver, 20);
WebElement inputField = waiter.until(ExpectedConditions.presenceOfElementLocated(By.id("inputField")));
inputField.sendKeys("Test input");
WebElement submitInput = waiter.until(ExpectedConditions.presenceOfElementLocated(By.id("submitInput")));
submitInput.click();
WebElement feedback = waiter.until(ExpectedConditions.presenceOfElementLocated(By.id("feedback")));
Assert.assertTrue("Feedback not was not empty, but was: " + feedback.getText(), feedback.getText().isEmpty());
問題は、selenium docssubmitInput.click()
のようにイベントを介して新しいページが読み込まれると、すぐに完了して戻ることです。したがって、「フィードバック」による取得の呼び出しは正常に機能し、デバッグを通じて、要素が正しく取得されることがわかります。ただし、ページがバックグラウンドで更新されたため、を呼び出すとが表示されます。StaleElementException
feedback.getText()
次の方法なしでテストに合格するにはどうすればよいですか。
- Thread.sleep()を追加します。
StaleElementException
要素を再フェッチするためのキャッチを追加します。
注:上記のテストは、ページが更新されていないために入力が無効な場合に機能しますが、入力が有効な場合には機能しません。
どんな助けでも大歓迎です。
編集:これは、要素が表示されるまでページをポーリングする場合の問題ではなく、submitInput.click()
新しいページをロードするか、既存のラベルにテキストを追加するかを検出する場合の問題であることに注意してください。
編集2:問題を説明するために、テストログとサーバーログをインターリーブするタイムログランスルーをコンパイルしました。
16:34:48,589 - TEST - Navigating to page.
16:34:48,605 - SERVER - Page request started.
16:34:48,631 - SERVER - Page request ended.
16:34:49,050 - TEST - Typing test input.
16:34:49,456 - TEST - Clicking button.
16:34:49,519 - SERVER - Received click event.
16:34:49,529 - SERVER - Responding with redirect.
16:34:49,556 - TEST - Finding feedback by id.
16:34:49,560 - SERVER - Page request started.
16:34:49,581 - SERVER - Page request ended.
16:34:49,775 - TEST - Test threw exception.
サーバーは、テストから送信されてから0.5秒強でクリックイベントを受信することがわかります。すぐに(この場合は)リダイレクトコマンドで応答します。その間、クリックがAJAXイベントであるため、ドキュメントに従ってテストがバックグラウンドで続行されました。これにより、サーバーが新しいページ要求を受信する0.004秒前に、テストでフィードバックが取得されます(ご覧のとおり)。feedback.getText()
解析されてChromeDriverに送信されるまでに、サーバーはすでに新しいページで応答しているため、この関数は古い例外を返します。
重要な点は、を使用してこれをうまく修正できることですThread.sleep(1000)
が、これは理想からはほど遠いです。1つは、サーバーがAJAXを解析して結果を返すのに0.5秒以上かかる場合があるためです。これにより、テストが非決定的になります。2つ目は、これらの時間がすぐに積み重なって時間を浪費するためです。数ミリ秒が必要でした。