Selenium:如何使 Web 驱动程序在执行另一个测试之前等待页面刷新
Posted
技术标签:
【中文标题】Selenium:如何使 Web 驱动程序在执行另一个测试之前等待页面刷新【英文标题】:Selenium: How to make the web driver to wait for page to refresh before executing another test 【发布时间】:2012-10-26 00:05:55 【问题描述】:我正在 TestNG 中使用 Selenium Web 驱动程序编写测试用例,并且我有一个场景是我正在按顺序运行多个测试(请参阅下文)
@Test(priority =1)
public void Test1()
@Test(priority =2)
public void Test2()
两个测试都是 AJAX 调用,其中会打开一个对话框,执行测试,然后关闭对话框,然后在页面顶部显示一条通知消息,每次成功测试后页面都会刷新。
问题是: Test2 不等待页面刷新/重新加载。假设当 Test1 成功完成时, Test2 将在页面刷新之前启动(即它打开对话框,执行场景等)同时页面刷新(这必然发生在成功执行 Test1 之后)。现在由于页面刷新,由于Test2打开的对话框不再存在,然后Test2失败。
(另外,我不知道刷新页面需要多长时间。因此,我不想在执行Test2之前使用Thread.sleep(xxxx))
我也不觉得
driver.navigate().refresh()
将通过将它放在 Test2 之前解决我的问题,因为在这种情况下,我的页面将被刷新两次。问题是通过代码发生的刷新(不确定,因为它可能需要 1 秒或 3 秒或 5 秒)
【问题讨论】:
我有一个类似的场景 - 在确认对话框要求继续之前加载不确定 - 没有页面刷新。网页已加载 - 它正在处理 ajax。想要确认对话框是否出现。 关于测试范围的一般问题:成功重新加载不是测试的一部分吗?我会假设是这样,所以我会在测试 #1 结束时检查页面是否重新加载,然后测试 #2 甚至一开始就没有这个问题,因为问题是在测试 #1 结束时处理的(或者在 @AfterMethod 如果你不关心结果/不认为它真的是测试的一部分) 【参考方案1】:如果您正在等待元素出现,那么
在 selenium rc 中,我们曾经使用 selenium.WaitForCondition("selenium.isElementPresent(\"fContent\")", "desiredTimeoutInMilisec")
来做到这一点
在 web 驱动中你可以使用这个实现同样的事情
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);
这样你可以在执行你的 test2 之前等待你的元素出现。
更新:
如果您正在等待页面加载,则可以在 Web 驱动程序中使用此代码:
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);
【讨论】:
我不想等待元素出现。我想等待页面重新加载/刷新,然后我只想执行 Test2 根据问题,我想在执行您的 test1 后页面会刷新,因此您无法获得执行测试用例 2 的所需元素。 问题是,如果您正在等待页面刷新,那么您不能等待元素 - 因为它们已经在页面上 但是当 WebDriver 继续运行时,元素通常不在最终位置。因此它们已加载但无法点击。 waitForPageLoaded(WebDriver webdriver) 函数在我的情况下完美运行!非常感谢【参考方案2】:Here 是 C#.Net 中 WaitForPageLoad
实现的更好且经过测试的版本
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;
【讨论】:
这在 ruby 中会是什么样子? 太棒了! IWebElemt::click() 是否导致 html 或 Javascript 无关紧要。这个解决方案就像一个魅力。【参考方案3】:如果您可以触发 URL 更改,这将起作用:
WebDriverWait wait = new WebDriverWait(yourDriver, TimeSpan.FromSeconds(5));
wait.Until(ExpectedConditions.UrlContains("/url-fragment"));
【讨论】:
以上是关于Selenium:如何使 Web 驱动程序在执行另一个测试之前等待页面刷新的主要内容,如果未能解决你的问题,请参考以下文章
python+selenium 如何变例输入使之每次执行脚本时都自增1
Selenium Web 驱动程序 Firefox 打开空白页
带有Python的Selenium Webdriver - 无法使用Selenium Web驱动程序在Web应用程序中提供输入(Date)