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:等到(...)关键字

等到页面加载 Selenium Python

Selenium WebElement.Click() 是不是等到加载下一页?

selenium常用的API设置get方法最大加载时间

selenium基础用法