首页 文章

等待Selenium中的页面加载

提问于
浏览

30 回答

  • 0

    如果有人使用硒化物:

    public static final Long SHORT_WAIT = 5000L; // 5 seconds
    $("some_css_selector").waitUntil(Condition.appear, SHORT_WAIT);
    

    更多条件可以在这里找到:http://selenide.org/javadoc/3.0/com/codeborne/selenide/Condition.html

  • 2

    所有这些解决方案都适用于特定情况,但它们至少会遇到以下几个问题之一:

    • 它们不够通用 - 它们希望您提前知道某些特定条件对于您要访问的页面是否正确(例如,将显示某个元素)

    • 他们对竞争条件持开放态度,您可以使用旧页面上实际存在的元素以及新页面 .

    这是我尝试避免这个问题的通用解决方案(在Python中):

    首先,一个通用的“等待”函数(如果你愿意,可以使用WebDriverWait,我发现它们很难看):

    def wait_for(condition_function):
        start_time = time.time()
        while time.time() < start_time + 3:
            if condition_function():
                return True
            else:
                time.sleep(0.1)
        raise Exception('Timeout waiting for {}'.format(condition_function.__name__))
    

    接下来,该解决方案依赖于selenium为页面上的所有元素记录(内部)id号的事实,包括顶级 <html> 元素 . 当页面刷新或加载时,它会获得一个带有新ID的新html元素 .

    因此,假设您要单击带有文本“我的链接”的链接,例如:

    old_page = browser.find_element_by_tag_name('html')
    
    browser.find_element_by_link_text('my link').click()
    
    def page_has_loaded():
        new_page = browser.find_element_by_tag_name('html')
        return new_page.id != old_page.id
    
    wait_for(page_has_loaded)
    

    对于更多Pythonic,可重用的通用助手,您可以创建一个上下文管理器:

    from contextlib import contextmanager
    
    @contextmanager
    def wait_for_page_load(browser):
        old_page = browser.find_element_by_tag_name('html')
    
        yield
    
        def page_has_loaded():
            new_page = browser.find_element_by_tag_name('html')
            return new_page.id != old_page.id
    
        wait_for(page_has_loaded)
    

    然后你可以在任何硒交互中使用它:

    with wait_for_page_load(browser):
        browser.find_element_by_link_text('my link').click()
    

    我认为那是防弹的!你怎么看?

    更多信息blog post about it here

  • 0

    Ruby实现:

    wait = Selenium::WebDriver::Wait.new(:timeout => 10)
    wait.until {
        @driver.execute_script("return document.readyState;") == "complete" 
    }
    
  • 8

    您可以使用以下现有方法在下面的示例中设置pageeLoadTimeout的时间,如果页面加载时间超过20秒,则会抛出页面重新加载的异常

    WebDriver driver = new FirefoxDriver();
    driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS)
    
  • 0

    SeleniumWaiter

    import com.google.common.base.Function;
    import org.openqa.selenium.By;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.support.ui.WebDriverWait;
    
    public class SeleniumWaiter {
    
          private WebDriver driver;
    
          public SeleniumWaiter(WebDriver driver) {
               this.driver = driver;
          }
    
          public WebElement waitForMe(By locatorname, int timeout){
               WebDriverWait wait = new WebDriverWait(driver, timeout);
               return wait.until(SeleniumWaiter.presenceOfElementLocated(locatorname));
          }
    
          public static Function<WebDriver, WebElement> presenceOfElementLocated(final By locator) {
                // TODO Auto-generated method stub
                return new Function<WebDriver, WebElement>() {
                     @Override
                     public WebElement apply(WebDriver driver) {
                          return driver.findElement(locator);
                     }
                };
          }
     }
    

    给你 use it

    _waiter = new SeleniumWaiter(_driver);
    
    try {
       _waiter.waitForMe(By.xpath("//..."), 10);
    } 
    catch (Exception e) {
       // Error
    }
    
  • 2

    我的简单方法:

    long timeOut = 5000;
        long end = System.currentTimeMillis() + timeOut;
    
            while (System.currentTimeMillis() < end) {
    
                if (String.valueOf(
                        ((JavascriptExecutor) driver)
                                .executeScript("return document.readyState"))
                        .equals("complete")) {
                    break;
                }
            }
    
  • 2

    我是第一个选择,因为您通常知道您将在等待加载的页面上与下一个交互的元素 . 我的方法一直是构建谓词/函数,如 waitForElementByID(String id)waitForElemetVisibleByClass(String className) 等,然后在我需要的地方使用和重用它们,无论是页面加载还是页面内容更改,我都在等待 .

    例如,

    在我的测试类中:

    driverWait.until(textIsPresent("expectedText");
    

    在我的测试类父级中:

    protected Predicate<WebDriver> textIsPresent(String text){
        final String t = text;
        return new Predicate<WebDriver>(){
            public boolean apply(WebDriver driver){
                return isTextPresent(t);
            }
        };
    }
    
    protected boolean isTextPresent(String text){
        return driver.getPageSource().contains(text);
    }
    

    虽然这看起来很多,但它会为您重复检查,并且可以在超时之前设置检查频率的间隔以及最终等待时间 . 此外,您将重用此类方法 .

    在此示例中,父类定义并启动了 WebDriver driverWebDriverWait driverWait .

    我希望这有帮助 .

  • 1

    隐式使用等待页面上每个元素的等待直到给定时间 .

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

    这等待页面上的每个元素持续30秒 .

    另一个等待是在此等待中显式等待或有条件等待,直到给定条件 .

    WebDriverWait wait = new WebDriverWait(driver, 40);
    WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));
    

    在id中,只要加载页面,就会在页面上显着地显示静态元素id .

  • 11
    /**
     * Call this method before an event that will change the page.
     */
    private void beforePageLoad() {
        JavascriptExecutor js = (JavascriptExecutor) driver;
        js.executeScript("document.mpPageReloaded='notYet';");
    }
    
    /**
     * Call this method after an event that will change the page.
     * 
     * @see #beforePageLoad
     * 
     *      Waits for the previous page to disappear.
     */
    private void afterPageLoad() throws Exception {
        (new WebDriverWait(driver, 10)).until(new Predicate<WebDriver>() {
    
            @Override
            public boolean apply(WebDriver driver) {
                JavascriptExecutor js = (JavascriptExecutor) driver;
                Object obj = js.executeScript("return document.mpPageReloaded;");
                if (obj == null) {
                    return true;
                }
                String str = (String) obj;
                if (!str.equals("notYet")) {
                    return true;
                }
                return false;
            }
        });
    }
    

    在仅更改文档的一部分的情况下,您可以从文档更改为元素 .

    这项技术的灵感来自于自上而下的答案 .

  • 120

    使用类WebDriverWait

    另见here

    你可以期待展示一些元素 . 像C#中的东西:

    WebDriver _driver = new WebDriver();
    WebDriverWait _wait = new WebDriverWait(_driver, new TimeSpan(0, 1, 0));
    
    _wait.Until(d => d.FindElement(By.Id("Id_Your_UIElement"));
    
  • 11

    使用WebDriver的Java绑定时等待页面加载的最佳方法是使用PageFart设计模式和PageFactory . 这允许您使用 AjaxElementLocatorFactory ,它只是作为所有元素的全局等待 . 它对诸如下拉框或复杂的javascript转换等元素有限制,但它会大大减少所需的代码量并加快测试时间 . 在这篇博文中可以找到一个很好的例子 . 假设对Core Java有基本的了解 .

    http://startingwithseleniumwebdriver.blogspot.ro/2015/02/wait-in-page-factory.html

  • 1
    • WebDriver driver = new ff / chrome / anyDriverYouWish(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); 等待最多10秒 .

    • WebDriverWait wait = new WebDriverWait(driver, 10); wait.until(ExpectedConditions.visibilityOf(WebElement element));

    • FluentWait<Driver> fluentWait; fluentWait = new FluentWait<>(driver).withTimeout(30, TimeUnit.SECONDS) .pollingEvery(200, TimeUnit.MILLISECONDS) .ignoring(NoSuchElementException.class);

    最后一个选项的优点是您可以包含预期的异常,以便继续执行 .

  • 0

    如果设置驱动程序的隐式等待,然后对预期在加载页面上的元素调用 findElement 方法,则WebDriver将轮询该元素,直到找到该元素或达到超时值 .

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

    来源:implicit-waits

  • 4

    如果要等待加载特定元素,可以在 RenderedWebElement 上使用 isDisplayed() 方法:

    // Sleep until the div we want is visible or 5 seconds is over
    long end = System.currentTimeMillis() + 5000;
    while (System.currentTimeMillis() < end) {
        // Browsers which render content (such as Firefox and IE) return "RenderedWebElements"
        RenderedWebElement resultsDiv = (RenderedWebElement) driver.findElement(By.className("gac_m"));
    
        // If results have been returned, the results are displayed in a drop down.
        if (resultsDiv.isDisplayed()) {
          break;
        }
    }
    

    (例子来自The 5 Minute Getting Started Guide

  • 84

    NodeJS Solution:

    Nodejs 你可以通过承诺得到它...

    如果您编写此代码,则可以确保在到达当时页面已完全加载...

    driver.get('www.sidanmor.com').then(()=> {
        // here the page is fully loaded!!!
        // do your stuff...
    }).catch(console.log.bind(console));
    

    如果您编写此代码,您将导航,selenium将等待3秒......

    driver.get('www.sidanmor.com');
    driver.sleep(3000);
    // you can't be sure that the page is fully loaded!!!
    // do your stuff... hope it will be OK...
    

    来自Selenium文档:

    this.get(url)→那么

    安排命令导航到给定的URL .

    返回在文档具有 finished loading 时将解析的promise .

    Selenium Documentation (Nodejs)

  • 30

    你可以使用等待 . 在硒中基本上有两种等待

    • 隐含等待

    • 明确等待

    - Implicit wait

    这很简单请看下面的语法:

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

    - Explicit wait

    明确地等待或条件等待在此等待直到给定条件发生 .

    WebDriverWait wait = new WebDriverWait(driver, 40);
    WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));
    

    您可以使用其他属性,如 visblityOf()visblityOfElement()

  • 21
    driver.asserts().assertElementFound("Page was not loaded",
    By.xpath("//div[@id='actionsContainer']"),Constants.LOOKUP_TIMEOUT);
    
  • 15

    How to get Selenium to wait for page load after a click提供了以下有趣的方法:

    • 从旧页面存储对 WebElement 的引用 .

    • 单击链接 .

    • 继续调用 WebElement 上的操作,直到抛出 StaleElementReferenceException .

    示例代码:

    WebElement link = ...;
    link.click();
    new WebDriverWait(webDriver, timeout).until((org.openqa.selenium.WebDriver input) ->
    {
        try
        {
            link.isDisplayed();
            return false;
        }
        catch (StaleElementReferenceException unused)
        {
            return true;
        }
    });
    
  • 9

    使用if条件和任何存在的元素

    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    
  • 4

    这似乎是WebDriver的严重限制 . 显然等待一个元素并不意味着页面被加载,特别是DOM可以完全构建(onready状态),JS仍在执行,CSS和图像仍在加载 .

    我相信最简单的解决方案是在初始化所有内容后在onload事件上设置一个JS变量,并在Selenium中检查并等待这个JS变量 .

  • 3

    您还可以使用以下代码检查pageloaded

    IWait<IWebDriver> wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(30.00));
    
     wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));
    
  • 0

    您可以显式等待元素显示在网页上,然后才能执行任何操作(如element.click())

    driver.get("http://somedomain/url_that_delays_loading");
    WebElement myDynamicElement = (new WebDriverWait(driver, 10))
      .until(new ExpectedCondition<WebElement>(){
            @Override
            public WebElement apply(WebDriver d) {
            return d.findElement(By.id("myDynamicElement"));
    }});
    

    这是我用于类似场景的工作,它工作正常 .

  • 4

    通常,使用Selenium 2.0时,Web驱动程序只应在确定页面已加载后才将控制权返回给调用代码 . 如果没有,你可以调用 waitforelemement ,它循环调用 findelement 直到它被找到或超时(可以设置超时) .

  • 2

    调用以下功能

    public static boolean isloadComplete(WebDriver driver)
    {
        return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
                || ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
    }
    
  • 0

    您可以尝试使用此代码让页面完全加载,直到找到元素 .

    public void waitForBrowserToLoadCompletely() {
        String state = null;
        String oldstate = null;
        try {
            System.out.print("Waiting for browser loading to complete");
    
            int i = 0;
            while (i < 5) {
                Thread.sleep(1000);
                state = ((JavascriptExecutor) driver).executeScript("return document.readyState;").toString();
                System.out.print("." + Character.toUpperCase(state.charAt(0)) + ".");
                if (state.equals("interactive") || state.equals("loading"))
                    break;
                /*
                 * If browser in 'complete' state since last X seconds. Return.
                 */
    
                if (i == 1 && state.equals("complete")) {
                    System.out.println();
                    return;
                }
                i++;
            }
            i = 0;
            oldstate = null;
            Thread.sleep(2000);
    
            /*
             * Now wait for state to become complete
             */
            while (true) {
                state = ((JavascriptExecutor) driver).executeScript("return document.readyState;").toString();
                System.out.print("." + state.charAt(0) + ".");
                if (state.equals("complete"))
                    break;
    
                if (state.equals(oldstate))
                    i++;
                else
                    i = 0;
                /*
                 * If browser state is same (loading/interactive) since last 60
                 * secs. Refresh the page.
                 */
                if (i == 15 && state.equals("loading")) {
                    System.out.println("\nBrowser in " + state + " state since last 60 secs. So refreshing browser.");
                    driver.navigate().refresh();
                    System.out.print("Waiting for browser loading to complete");
                    i = 0;
                } else if (i == 6 && state.equals("interactive")) {
                    System.out.println(
                            "\nBrowser in " + state + " state since last 30 secs. So starting with execution.");
                    return;
                }
    
                Thread.sleep(4000);
                oldstate = state;
    
            }
            System.out.println();
    
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        }
    }
    
  • 30

    您还可以使用类: ExpectedConditions 显式等待元素显示在网页上,然后您可以采取任何操作进一步操作

    您可以使用 ExpectedConditions 类来确定元素是否可见:

    WebElement element = (new WebDriverWait(getDriver(), 10)).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("input#houseName")));
    

    有关您可以检查的所有条件的列表,请参阅 ExpectedConditions class Javadoc .

  • 9

    您可以删除 System.out 行 . 它是为了调试目的而添加的 .

    WebDriver driver_;
    
    public void waitForPageLoad() {
    
        Wait<WebDriver> wait = new WebDriverWait(driver_, 30);
        wait.until(new Function<WebDriver, Boolean>() {
            public Boolean apply(WebDriver driver) {
                System.out.println("Current Window State       : "
                    + String.valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState")));
                return String
                    .valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState"))
                    .equals("complete");
            }
        });
    }
    
  • 2

    在此等待中明确等待或有条件等待,直到给出此条件 .

    WebDriverWait wait = new WebDriverWait(wb, 60);
    wait.until(ExpectedConditions.elementToBeClickable(By.name("value")));
    

    这将等待每个web元素60秒 .

    隐式使用等待页面上每个元素的等待直到给定时间 .

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

    这将等待每个web元素60秒 .

  • 3

    最简单的方法是等待一些元素出现在加载的页面上 .

    如果您想在页面加载后单击某个按钮,可以使用等待并单击:

    await().until().at.most(20, TimeUnit.Seconds).some_element.isDisplayed(); // or another condition
    getDriver().find(some_element).click;
    
  • 1

    Imran的回答重新针对Java 7:

    WebDriverWait wait = new WebDriverWait(driver, 30);
    
        wait.until(new ExpectedCondition<Boolean>() {
            public Boolean apply(WebDriver wdriver) {
                return ((JavascriptExecutor) driver).executeScript(
                    "return document.readyState"
                ).equals("complete");
            }
        });
    

相关问题