【问题标题】:How to properly configure Implicit / Explicit Waits and pageLoadTimeout through Selenium?如何通过 Selenium 正确配置隐式/显式等待和 pageLoadTimeout?
【发布时间】:2018-11-04 05:16:30
【问题描述】:

我目前有以下设置,但我不确定我的等待(隐式和 pageLoadTimeout)是否正常工作。 这是正确的实现吗? 通过将它放在@Before("@setup") 中,它是否适用于每个场景或步骤定义运行?每次我调用@Given、@When..etc 时,驱动程序会相应地等待吗?

@Before("@setup")
    public void setUp() {

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


    }

为什么需要给下面的等待分配一个WebElement, WebElement 元素接收什么?这是正确的实施吗? -

 WebDriverWait wait = new WebDriverWait(driver, 30);
 WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(id)));
boolean status = element.isDisplayed();

【问题讨论】:

    标签: java selenium page-load-time webdriverwait implicitwait


    【解决方案1】:

    隐式等待()

    implicitlyWait() 是告诉 WebDriver 实例,即 driver 在尝试查找一个或多个元素时轮询HTML DOM 一段时间,如果他们无法立即使用。默认等待配置设置为 0。设置后,隐式等待会在 WebDriver 对象实例的生命周期内设置。

    您的代码试用非常完美,如下所示:

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

    这里有详细的讨论Using implicit wait in selenium


    pageLoadTimeout()

    pageLoadTimeout() 设置在引发错误之前等待页面加载完成的时间跨度。

    您的代码试用非常完美,如下所示:

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

    您可以在这里找到pageLoadTimeout in Selenium not working的详细讨论

    注意:尽量避免配置pageLoadTimeout(),除非测试规范明确提及。


    为什么选择 WebDriverWait?

    现代浏览器使用JavaScript、AJAX 和React Native,其中网页中的元素是动态加载的。因此,在继续执行下一行代码之前等待满足特定条件 Explicit Waits 即 WebDriverWait 是继续前进的方式。

    注意:根据Explicit and Implicit Waits的官方文档,不要混用隐式和显式等待。这样做会导致不可预测的等待时间。

    您的代码试验非常适合等待元素的可见性,如下所示:

    WebDriverWait wait = new WebDriverWait(driver, 30);
    WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(id)));
    

    这里可以找到Replace implicit wait with explicit wait (selenium webdriver & java)的详细讨论


    您的具体问题

    • 为什么需要将 WebElement 分配给以下等待:WebDriverWait 与 ExpectedConditions 一起不仅返回 WebElement,还取决于ExpectedConditions 也可以返回 void、Boolean、List。

    • WebElement 元素接收什么?:根据您使用 ExpectedConditions 作为visibilityOfElementLocated() 的代码块,WebElement一旦元素存在在网页的DOM Tree 上并且可见,> 将被返回。 可见性表示元素不仅显示,而且高度和宽度都大于0。

    • 这是正确的实现吗?:您的实现接近完美,但最后一行代码,即boolean status = element.isDisplayed(); 是多余的,因为一旦元素为 visibilityOfElementLocated() 就会返回元素>可见(即元素不仅显示,而且高度和宽度都大于0)。

    【讨论】:

    • 很好的详细答案。
    • 谢谢老兄!
    【解决方案2】:

    如果您刚开始使用 selenium,这是一个合法的问题。我总是建议看看official doc。

    隐式等待是告诉 WebDriver 轮询 DOM 尝试查找一个或多个元素(如果它们是)时的时间量 无法立即使用。默认设置为 0。一旦设置, 为 WebDriver 对象实例的生命周期设置了隐式等待。

    例子:

    WebDriver driver = new FirefoxDriver();
    driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
    driver.get("http://somedomain/url_that_delays_loading");
    WebElement myDynamicElement = driver.findElement(By.id("myDynamicElement"));
    

    在这种情况下,如果 DOM 中不存在 ID 为 myDynamicElement 的 Web 元素,则当您尝试定位它时,您表示要重试直到 10 秒。轮询时间取决于您使用的网络驱动程序。你必须知道的是它会在 10 秒内尝试查找元素。当然,如果元素位于这个时间结束之前,代码会继续。否则抛出异常。

    显式等待是您定义的等待特定条件的代码 在继续代码之前发生。最坏的情况是 Thread.sleep(),它将条件设置为一个确切的时间段 等待。提供了一些方便的方法来帮助您编写 只等待所需时间的代码。 WebDriverWait in 与 ExpectedCondition 结合是一种方法 完成。

    例子:

    WebDriver driver = new FirefoxDriver();
    driver.get("http://somedomain/url_that_delays_loading");
    WebElement myDynamicElement = (new WebDriverWait(driver, 10))
      .until(ExpectedConditions.presenceOfElementLocated(By.id("myDynamicElement")));
    

    在抛出 TimeoutException 或如果 它发现元素将在 0 - 10 秒内返回它。 WebDriverWait 默认情况下,每 500 毫秒调用一次 ExpectedCondition,直到它 成功返回。的成功返回值 ExpectedCondition 函数类型是布尔值 true,或 非空对象。

    而且,最后写着:这个例子在功能上也等同于第一个隐式等待例子。

    因此,如果您使用 presenceOfElementLocated 作为预期条件(对于您尝试定位的每个元素),则与使用隐式等待完全相同。但条件不只是这个。从ExpectedConditions 可以看出,您可以指定其他条件(例如:elementToBeClickable、stalenessOf 等)。

    所以,回到你的问题:

    有

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

    你是说要等待,每当你试图定位一个元素,存在(记住,它就像存在的元素定位)直到 30 秒.

    有

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

    您将需要加载网页的时间设置为 30 秒。

    与:

     WebDriverWait wait = new WebDriverWait(driver, 30);
     WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id(id)));
    boolean status = element.isDisplayed();
    

    您是说要等待 id:"id" 的 web 元素的 visibilityOfElementLocated,直到 30 秒。

    最后:

    为什么要给后面的wait分配一个WebElement, WebElement 元素接收什么?这是对的吗 实施?

    WebElement 元素接收什么?如果不是带有 id:"id" 的 webelement,还有什么?当然,如果它是可见的。否则会抛出异常。

    【讨论】:

      【解决方案3】:

      在你的情况下,你只需要等待页面加载,你的实现就可以了。 @ Before 是 Cucumber Hooks 之一,这意味着您的方法将在每个场景之前运行。 我建议使用 fluent wait 而不是 webdriverwait,原因如下:

      使用 FluentWait 实例时:

      1. 您可以检查已定义的条件(...的可见性、不可见性)
      2. 忽略特定类型的异常等待,例如 NoSuchElementExceptions 或在页面上搜索元素时出现 StaleElementException。
      3. 您可以为每个条件指定轮询和超时。

      例如:

       // Waiting 30 seconds for an element to be present on the page, checking for its presence once every 5 seconds. 
      
      Wait<WebDriver> wait = new FluentWait<WebDriver>(driver) .withTimeout(30, SECONDS) .pollingEvery(5, SECONDS).ignoring(NoSuchElementException.class);
      

      希望我能帮上忙。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-28
        • 2018-01-24
        • 2023-04-08
        • 2017-04-19
        • 2020-06-30
        • 2012-05-11
        相关资源
        最近更新 更多