Selenium: как заставить веб-драйвер ждать обновления страницы перед выполнением другого теста
Я пишу тестовые примеры, используя Selenium web Driver в TestNG, и у меня есть сценарий, в котором я выполняю несколько тестов последовательно (см. ниже)
@Test(priority =1)
public void Test1(){
}
@Test(priority =2)
public void Test2(){
}
Оба теста - это вызовы AJAX, где открывается диалоговое окно, тесты выполняются, затем диалоговое окно закрывается, а затем появляется сообщение уведомления вверху страницы и после каждого успешного теста страница обновляется.
Проблема заключается в следующем: Test2 не дожидается обновления или перезагрузки страницы. Предположим, что когда Test1 успешно завершен, Test2 начнется до обновления страницы (т.е. откроет диалоговое окно, выполнит сценарии и т.д.), В то время как страница обновится (что должно было произойти после успешного выполнения Test1). Теперь, когда страница обновляется, окно diaog, открытое из-за Test2, больше не присутствует, а затем Test2 терпит неудачу.
(Кроме того, я не знаю, сколько времени потребуется для обновления страницы. Поэтому я не хочу использовать Thread.sleep(xxxx) перед выполнением Test2)
Кроме того, я не думаю, что
driver.navigate().refresh()
решит мою проблему, поставив ее перед Test2, так как в этом случае моя страница будет обновляться дважды. Проблема заключается в обновлении, которое происходит через код (что неопределенно, так как это может занять 1 сек или 3 с или 5 секунд)
Ответы
Ответ 1
Если вы ожидаете появления элемента, то
В селене rc мы использовали это, используя selenium.WaitForCondition( "selenium.isElementPresent(\" fContent\ ")", "wishTimeoutInMilisec" )
В веб-драйвере U можно добиться того же, используя этот
WebDriverWait myWait = new WebDriverWait(webDriver, 45);
ExpectedCondition<Boolean> conditionToCheck = new ExpectedCondition<Boolean>()
{
@Override
public Boolean apply(WebDriver input) {
return (input.findElements(By.id("fContent")).size() > 0);
}
};
myWait.until(conditionToCheck);
Таким образом, вы можете дождаться присутствия вашего элемента перед выполнением теста2.
ОБНОВЛЕНО:
Если вы ожидаете загрузки страницы, то в веб-драйвере вы можете использовать этот код:
public void waitForPageLoaded(WebDriver driver)
{
ExpectedCondition<Boolean> expectation = new
ExpectedCondition<Boolean>()
{
public Boolean apply(WebDriver driver)
{
return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
}
};
Wait<WebDriver> wait = new WebDriverWait(driver,30);
try
{
wait.until(expectation);
}
catch(Throwable error)
{
assertFalse("Timeout waiting for Page Load Request to complete.",true);
}
}
Ответ 2
Здесь лучше и проверена версия реализации WaitForPageLoad
в С#.Net
public void WaitForPageLoad(int maxWaitTimeInSeconds) {
string state = string.Empty;
try {
WebDriverWait wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(maxWaitTimeInSeconds));
//Checks every 500 ms whether predicate returns true if returns exit otherwise keep trying till it returns ture
wait.Until(d = > {
try {
state = ((IJavaScriptExecutor) _driver).ExecuteScript(@"return document.readyState").ToString();
} catch (InvalidOperationException) {
//Ignore
} catch (NoSuchWindowException) {
//when popup is closed, switch to last windows
_driver.SwitchTo().Window(_driver.WindowHandles.Last());
}
//In IE7 there are chances we may get state as loaded instead of complete
return (state.Equals("complete", StringComparison.InvariantCultureIgnoreCase) || state.Equals("loaded", StringComparison.InvariantCultureIgnoreCase));
});
} catch (TimeoutException) {
//sometimes Page remains in Interactive mode and never becomes Complete, then we can still try to access the controls
if (!state.Equals("interactive", StringComparison.InvariantCultureIgnoreCase))
throw;
} catch (NullReferenceException) {
//sometimes Page remains in Interactive mode and never becomes Complete, then we can still try to access the controls
if (!state.Equals("interactive", StringComparison.InvariantCultureIgnoreCase))
throw;
} catch (WebDriverException) {
if (_driver.WindowHandles.Count == 1) {
_driver.SwitchTo().Window(_driver.WindowHandles[0]);
}
state = ((IJavaScriptExecutor) _driver).ExecuteScript(@"return document.readyState").ToString();
if (!(state.Equals("complete", StringComparison.InvariantCultureIgnoreCase) || state.Equals("loaded", StringComparison.InvariantCultureIgnoreCase)))
throw;
}
}
Ответ 3
если вы можете вызвать изменение URL-адреса, это будет работать
WebDriverWait wait = new WebDriverWait(yourDriver, TimeSpan.FromSeconds(5));
wait.Until(ExpectedConditions.UrlContains("/url-fragment"));