我有一个页面,它有一个带有一个输入字段和一个提交按钮的小表单。提交按钮是 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());
问题是,submitInput.click()
如果通过事件加载新页面,则会立即完成并返回:selenium docs,因此通过“反馈”进行检索的调用工作正常,我可以通过调试看到它正确获取了元素,但是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.
您可以看到服务器在测试发送后仅半秒多一点就收到了点击事件。它立即响应(在这种情况下)重定向命令。由于单击是 AJAX 事件,因此根据文档在后台继续进行测试,这导致(如您所见)测试在服务器收到新页面请求之前 0.004 秒检索反馈。在feedback.getText()
解析并发送到 ChromeDriver 时,服务器已经响应了一个新页面,因此该函数返回过时异常。
关键是我可以使用 修复这个问题Thread.sleep(1000)
,但这远非理想;首先是因为在某些情况下,服务器解析 AJAX 并返回结果的时间可能超过半秒,这使得测试具有不确定性,其次因为这些时间很快就会堆积起来并浪费时间,通常是不必要的,当只有一个需要几毫秒。