【问题标题】:Selenium -- How to wait until page is completely loaded [duplicate]Selenium - 如何等到页面完全加载[重复]
【发布时间】: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 块中检索,因为一旦重绘元素,它的元素标识符就会改变。

标签: java selenium-webdriver


【解决方案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 个答案,您可以组合:

    1. 在创建 Web 驱动实例后立即设置隐式等待:

      _ = driver.Manage().Timeouts().ImplicitWait;

      这将尝试等到页面在每次页面导航或页面重新加载时完全加载。

    2. 页面导航后,调用 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"));
      
    3. 检查 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多