Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Selenium—这样混合隐式等待和显式等待可以吗?_Selenium_Selenium Webdriver_Webdriverwait - Fatal编程技术网

Selenium—这样混合隐式等待和显式等待可以吗?

Selenium—这样混合隐式等待和显式等待可以吗?,selenium,selenium-webdriver,webdriverwait,Selenium,Selenium Webdriver,Webdriverwait,下面是一个(来自“Lets Kode It”)用selenium和Java开发web自动化框架的例子但是,这不是一个java问题。您只需要了解这些语言中任何一种语言的selenium—javascript、python、ruby、c#和java 讲师开发了一个CustomDriver类,其方法/功能如下所示。该方法等待元素可单击,而不必在代码中的任何地方编写WebDriverWait语句。它首先将隐式等待设置为零,执行显式等待,然后将隐式等待设置为框架中使用的原始值 这种方法对我来说似乎没问题,

下面是一个(来自“Lets Kode It”)用selenium和Java开发web自动化框架的例子但是,这不是一个java问题。您只需要了解这些语言中任何一种语言的selenium—javascript、python、ruby、c#和java

讲师开发了一个CustomDriver类,其方法/功能如下所示。该方法等待元素可单击,而不必在代码中的任何地方编写
WebDriverWait
语句。它首先将隐式等待设置为零,执行显式等待,然后将隐式等待设置为框架中使用的原始值

这种方法对我来说似乎没问题,但我不确定。这样混合使用隐式和显式等待会导致任何问题吗

更新(2020年3月24日)-我已经知道混合隐式和显式等待被认为是一种不好的做法,因为它可能导致不可预测的等待时间。我不是在问不可预测的等待时间,因为已经有很多关于这方面的问题和文章了

相反,我要问的是,如果隐式等待在每次执行显式等待之前都设置为零,那么可以吗?这还会导致不可预测的等待问题吗?会不会引起其他问题

/*
 Click element when element is clickable
 @param locator - locator strategy, id=>example, name=>example, css=>#example,
                       tag=>example, xpath=>//example, link=>example
 @param timeout - Duration to try before timeout
 */
public void clickWhenReady(By locator, int timeout) {
    try {
        driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
        WebElement element = null;
        System.out.println("Waiting for max:: " + timeout + " seconds for element to be clickable");

        WebDriverWait wait = new WebDriverWait(driver, 15);
        element = wait.until(
                ExpectedConditions.elementToBeClickable(locator));
        element.click();
        System.out.println("Element clicked on the web page");
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    } catch (Exception e) {
        System.out.println("Element not appeared on the web page");
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    }
}

我不建议把它们混在一起。As
隐式等待
通常在WebDriver系统的
远程
端实现,这意味着它们在基于浏览器的驱动程序(例如:chromedriver.exe、IEDriverServer.exe)中处理,其中As
显式等待
在本地语言绑定(如Java、ruby、python等)上实现

下面是使用
远程服务器运行脚本时发生的典型示例

本地代码->远程服务器->远程服务器上的本地语言绑定->chromedriver.exe或IEDriverServer.exe等远程组件。如果涉及到网格,事情会变得更加复杂,因为它可能是链之间的另一层。

因此,当您混合使用隐式和显式等待时,最终可能会出现未定义的行为。此外,由于隐式等待是在驱动程序级别实现的,因此它们可能随时更改,并对脚本产生影响。所以,坚持显式等待和完全控制总是更好的


使用当前的技术,元素可能在元素出现后不久才渲染。因此,使用
隐式等待
是不够的,因此强烈建议使用
显式等待
。可能存在一些边缘情况,我们可能必须使用
隐式等待
,但是,如果您计划将来扩展脚本以在网格上运行/使用远程服务器,请不要将这两种情况混合使用。

使用隐式等待和显式等待的问题归结为在Selenium源代码中如何实现
ExpectedConditions
的缺陷

让我通过分析以下代码来解释问题:

WebDriver driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
WebElement element =  new WebDriverWait(driver, 5, 1000).until(ExpectedConditions.elementToBeClickable(By.id("some_id")));
  • 我们初始化驱动程序并将隐式等待设置为10秒。这意味着
    driver.findElement()
    将等待10秒,直到找到所有元素,然后抛出
    NoTouchElementException
    这是一个非常重要的注意事项
  • 然后我们设置了一个显式等待,持续时间为5秒,轮询之间的睡眠时间为1000毫秒(1秒)。这意味着
    WebDriverWait
    将每隔1秒到5秒轮询
    ExpectedConditions
    为true。如果
    ExpectedConditions
    返回true,轮询将停止,并返回
    ExpectedConditions
    中指定的对象。在上面的示例代码中,返回的对象是
    WebElement
    。如果
    ExpectedConditions
    在5秒后为false,则抛出
    TimeoutException
    或我们预期的那样)。现在是时候看看
    ExpectedConditions
    中发生了什么
  • ExpectedConditions.elementToBeClickable()
    代码具有以下语法

    public static ExpectedCondition<WebElement> elementToBeClickable(final By locator) {
        return new ExpectedCondition<WebElement>() {
            @Override
            public WebElement apply(WebDriver driver) {
                WebElement element = visibilityOfElementLocated(locator).apply(driver);
                try {
                    if (element != null && element.isEnabled()) {
                        return element;
                    }
                    return null;
                } catch (StaleElementReferenceException e) {
                    return null;
                }
            }
        };
    }
    
    5.注意上面在
    visibilityOfElementLocated()
    方法中如何调用
    driver.findElement(locator)
    。如果未找到该元素,将应用10秒的隐式等待。因此,驱动程序将等待10秒钟,直到它抛出
    NoTouchElementException

  • 但是等等(双关语不是故意的)!在
    elementtobelickable()
    条件下,我们的显式等待不是设置为5秒超时吗?是的,但将首先应用隐式等待。WebDriverWait将捕获
    NoTouchElementException
    ,并在10秒后抛出
    TimeoutException
    ,而不是设置5秒的显式等待。这就是问题解决方案试图解决的问题。该解决方案尝试将隐式等待设置为0秒,以便正确执行显式等待条件,然后重置隐式等待

    问题中提供的实现只需要一个细节就可以完成任务。隐式等待硬编码为3秒,这并不理想。如何将隐式等待作为全局通用常量提供是非常具体的。我们正在对驱动程序设置隐式等待,并且可以预期隐式等待,如“driver”
    driver.manage().timeout().getImplicitWait()
    。虽然理想,但不幸的是,这不可能直接实现。这里有一些解决方法,@forresthopkinsa在创建扩展驱动程序以获得隐式等待方面有着相当的优势

    更新(2020年3月24日)

    问:这种方法对我来说似乎不错,但我不确定。这样混合使用隐式和显式等待会导致任何问题吗

    我在问,如果隐式等待在每次执行显式等待之前都设置为零,那么可以吗?这还会导致不可预测的等待问题吗?它会导致其他问题吗?

    public static ExpectedCondition<WebElement> visibilityOfElementLocated(final By locator) { return new ExpectedCondition<WebElement>() { @Override public WebElement apply(WebDriver driver) { try { return elementIfVisible(driver.findElement(locator)); } catch (StaleElementReferenceException e) { return null; } } }; }