Selenium ——如何等待页面完全加载

我试图使用 Java 和 Selenium WebDriver 自动化一些测试用例:

  • 有一个名为“产品”的页面。当我点击“查看详细信息”链接 在“ Product”页面中,会出现一个包含项目详细信息的弹出窗口(模式对话框)。
  • 当我点击弹出窗口中的“关闭”按钮时,弹出窗口将关闭 页面会自动刷新(页面正在重新加载,内容保持不变)。
  • 关闭弹出窗口后,我需要点击“添加项”按钮在 但是当 WebDriver 试图找到“添加项”按钮时, 如果网速太快,WebDriver 可以找到并点击 元素

  • 但是,如果互联网是缓慢的,WebDriver 找到按钮之前 页面刷新,但只要 WebDriver 单击按钮,页面就会刷新,并出现 StaleElementReferenceException

  • 即使使用了不同的等待,所有的等待条件都会变为真实 (因为页面内容在重新加载之前和之后是相同的) 甚至在页面重新加载和 StaleElementReferenceException之前 发生。

如果在单击“ Add Item”按钮之前使用 Thread.sleep(3000);,则测试用例可以正常工作。对于这个问题还有其他解决办法吗?

377727 次浏览

3 answers, which you can combine:

  1. Set implicit wait immediately after creating the web driver instance:

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

    This will try to wait until the page is fully loaded on every page navigation or page reload.

  2. After page navigation, call JavaScript return document.readyState until "complete" is returned. The web driver instance can serve as JavaScript executor. Sample code:

    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. Check if the URL matches the pattern you expect.

yes stale element error is thrown when (taking your scenario) you have defined locator strategy to click on 'Add Item' first and then when you close the pop up the page gets refreshed hence the reference defined for 'Add Item' is lost in the memory so to overcome this you have to redefine the locator strategy for 'Add Item' again

understand it with a dummy code

// 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

There are two different ways to use delay in selenium one which is most commonly in use. Please try this:

driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);

second one which you can use that is simply try catch method by using that method you can get your desire result.if you want example code feel free to contact me defiantly I will provide related code

You can do this in many ways before clicking on add items:

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.

or:

wait.until(ExpectedConditions.visibilityOfElementLocated("urelement"));

You can also wait like this. If you want to wait until invisible of previous page element:

wait.until(ExpectedConditions.invisibilityOfElementLocated("urelement"));

Here is the link where you can find all the Selenium WebDriver APIs that can be used for wait and its documentation.

It seems that you need to wait for the page to be reloaded before clicking on the "Add" button. In this case you could wait for the "Add Item" element to become stale before clicking on the reloaded element:

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();