Selenium - 如何等到页面完全加载[重复]
Posted
技术标签:
【中文标题】Selenium - 如何等到页面完全加载[重复]【英文标题】:Selenium -- How to wait until page is completely loaded [duplicate] 【发布时间】:2016-08-04 01:40:05 【问题描述】:我正在尝试使用 Java 和 Selenium WebDriver 自动化一些测试用例。我有以下情况:
有一个名为“产品”的页面。当我单击“查看详细信息”链接时 在“产品”页面中,会出现一个包含项目详细信息的弹出窗口(模式对话框)。 当我单击弹出窗口中的“关闭”按钮时,弹出窗口关闭并 页面自动刷新(页面刚刚重新加载,内容保持不变)。关闭弹出窗口后,我需要单击 同一页。但是当 WebDriver 试图找到“添加项目”按钮时, 如果网速太快,WebDriver 可以找到并点击 元素。
但是如果网速很慢,WebDriver 会在
页面刷新,但只要 WebDriver 点击按钮,页面就会刷新并出现StaleElementReferenceException
。
StaleElementReferenceException
发生。
如果在单击“添加项目”按钮之前使用Thread.sleep(3000);
,则测试用例可以正常工作。这个问题还有其他解决方法吗?
【问题讨论】:
我使用 Selenium 隐式等待,但并没有解决问题 这个问题可以很容易地通过使用 WebDriverWait 来解决,它等待条件返回真值或非空值,直到发生超时。条件是,单击 try-catch 中的元素。在 try 中,单击元素,如果完成则返回 true,在 catch 中,捕获 StaleElementReferenceException 并返回 null。因此,如果单击导致 StaleElementException,则再次执行条件,直到单击成功或发生超时。这将有效地等待重新加载完成。 在上面的注释中补充一点:元素也应该在点击之前在 try 块中检索,因为一旦重绘元素,它的元素标识符就会改变。 【参考方案1】:在单击添加项目之前,您可以通过多种方式执行此操作:
WebDriverWait wait = new WebDriverWait(driver, 40);
wait.until(ExpectedConditions.elementToBeClickable(By.id("urelementid"))); // instead of id you can use cssSelector or xpath of your element.
或:
wait.until(ExpectedConditions.visibilityOfElementLocated("urelement"));
你也可以这样等待。如果你想等到上一个页面元素不可见:
wait.until(ExpectedConditions.invisibilityOfElementLocated("urelement"));
这里是the link,您可以在其中找到所有可用于wait
的 Selenium WebDriver API 及其文档。
【讨论】:
【参考方案2】:3 个答案,您可以组合:
在创建 Web 驱动实例后立即设置隐式等待:
_ = driver.Manage().Timeouts().ImplicitWait;
这将尝试等到页面在每次页面导航或页面重新加载时完全加载。
页面导航后,调用 javascript return document.readyState
直到返回 "complete"
。 Web 驱动程序实例可以作为 JavaScript 执行器。示例代码:
C#
new WebDriverWait(driver, MyDefaultTimeout).Until(
d => ((IJavaScriptExecutor) d).ExecuteScript("return document.readyState").Equals("complete"));
Java
new WebDriverWait(firefoxDriver, pageLoadTimeout).until(
webDriver -> ((JavascriptExecutor) webDriver).executeScript("return document.readyState").equals("complete"));
检查 URL 是否与您期望的模式匹配。
【讨论】:
driver.manage().timeouts().implicitlyWait() 在 java 中要求 2 个参数(long arg0,TimeUnit arg1)是超时还是什么? 我相信 python 是(随时将其添加到您的答案中): selenium.webdriver.support.ui.WebDriverWait(self.driver, 10).until(lambda d: d.execute_script( "return document.readyState") == "完成")【参考方案3】:在 selenium 中使用延迟有两种不同的方法,一种是最常用的。请试试这个:
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
您可以使用的第二个方法是通过使用该方法简单地尝试 catch 方法 你可以得到你想要的结果。如果你想要示例代码,请随时与我联系,我会提供相关代码
【讨论】:
最好用的是 Thread.sleep(miilis);【参考方案4】:您似乎需要等待页面重新加载后才能单击“添加”按钮。 在这种情况下,您可以等待“添加项目”元素过时,然后再单击重新加载的元素:
WebDriverWait wait = new WebDriverWait(driver, 20);
By addItem = By.xpath("//input[.='Add Item']");
// get the "Add Item" element
WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(addItem));
//trigger the reaload of the page
driver.findElement(By.id("...")).click();
// wait the element "Add Item" to become stale
wait.until(ExpectedConditions.stalenessOf(element));
// click on "Add Item" once the page is reloaded
wait.until(ExpectedConditions.presenceOfElementLocated(addItem)).click();
【讨论】:
完美的例子,以防您需要等待多个动作发生。【参考方案5】:是的,当您定义定位器策略以首先单击“添加项目”时(以您的场景),然后当您关闭弹出窗口时页面会刷新,因此会引发陈旧元素错误,因此为“添加项目”定义的引用是迷失在记忆中,因此要克服这个问题,您必须再次重新定义“添加项目”的定位器策略
用虚拟代码理解它
// clicking on view details
driver.findElement(By.id("")).click();
// closing the pop up
driver.findElement(By.id("")).click();
// and when you try to click on Add Item
driver.findElement(By.id("")).click();
// you get stale element exception as reference to add item is lost
// so to overcome this you have to re identify the locator strategy for add item
// Please note : this is one of the way to overcome stale element exception
// Step 1 please add a universal wait in your script like below
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS); // just after you have initiated browser
【讨论】:
以上是关于Selenium - 如何等到页面完全加载[重复]的主要内容,如果未能解决你的问题,请参考以下文章
Python 3.5 - Selenium - 如何处理新窗口并等到它完全加载?
Robotframework:Selenium2Lib:等到(...)关键字