【问题标题】:A wrapper for WebDriverWait that could take all kinds of ExpectedConditon?可以接受各种 ExpectedConditon 的 WebDriverWait 包装器?
【发布时间】:2017-05-15 19:01:56
【问题描述】:

我在 Java 中使用 Selenium 3.4。我正在测试一个不是很快的 UI 并使用隐式等待,这样我就不必关心每次加载需要几秒钟的时间手动显式等待。

但是,有时我还是需要显式等待。为此,我需要暂时禁用隐式等待。为避免代码混乱,我将以下方法放在驱动程序管理器类中:

public static void waitFor(ExpectedCondition<Boolean> condition,int timeoutSeconds) throws Exception {
    setImplicitWait(0);
    try {
        (new WebDriverWait(driver, timeoutSeconds)).until(condition);
    } finally {
        setImplicitWait(WAIT_REGULAR);
    }
}

setImplicitWait 方法很简单:

public static void setImplicitWait(int TimeoutSeconds) {
    logger.debug("Setting implicit wait to {} seconds",TimeoutSeconds);
    driver.manage().timeouts().implicitlyWait(TimeoutSeconds, TimeUnit.SECONDS);
}

因此,此设置适用于一些等待,例如:

DriverManager.waitFor(ExpectedConditions.invisibilityOfElementLocated(By.className("gridxLoad")), DriverManager.WAIT_HUGE);

但是,如果我尝试这个:

DriverManager.waitFor(ExpectedConditions.visibilityOfElementLocated(By.className("gridxMain")), DriverManager.WAIT_HUGE);

我得到一个编译错误:

DriverManager 类型中的方法waitFor(ExpectedCondition, int) 不适用于参数(ExpectedCondition, int)

如果我将方法定义中的参数类型更改为 ExpectedCondition&lt;WebElement&gt; ,那么第二次等待当然会成功,而第一次等待会引发编译错误。如果我尝试为ExpectedCondition&lt;WebElement&gt;ExpectedCondition&lt;Boolean&gt; 创建相同的方法,则会出现编译错误:

方法waitFor(ExpectedCondition, int)的擦除与DriverManager类型中的另一个方法相同

最后,如果我尝试将参数定义为 ExpectedCondition,我会在同一个小方法中收到大量编译警告:

ExpectedCondition 是原始类型。对泛型类型 ExpectedCondition 的引用应该被参数化

类型安全:ExpectedCondition 类型的表达式需要未经检查的转换才能符合 Function

类型安全:FluentWait 类型的泛型方法 until(Function) 的未经检查的调用 until(ExpectedCondition)

我也尝试过这样定义方法:

public static void waitFor(Function&lt;? super WebDriver,Object&gt; condition,int timeoutSeconds) throws Exception {

但随后该方法的两个调用都会引发编译器错误。

我该怎么办?使用原始的 ExpectedCondition 参数并忽略警告?

【问题讨论】:

  • 这可能没什么帮助,但是当我将项目升级到 Selenium 3.x 时遇到了此类问题。在广泛搜索解决方案后,我最终将其回滚到 2.53。如果我记得,最新版本不支持 ExpectedConditions,我无法获得任何其他方法来完成我想要的(elelementIsClickable)
  • 他们确实支持 ExpectedConditions 但需要更高版本的番石榴 - 所以可能是不同的问题。 ExpectedConditions 本身工作正常,这只是制定一个包装器。

标签: java selenium parameters wait


【解决方案1】:

我最终确实找到了我认为正确的解决方案:

public static void waitFor(ExpectedCondition<?> condition,int timeoutSeconds) throws Exception {
    setImplicitWait(0);
    try {
        (new WebDriverWait(driver, timeoutSeconds)).until(condition);
    } finally {
        setImplicitWait(WAIT_REGULAR);
    }
}

【讨论】:

    【解决方案2】:

    我正在使用这些包装方法来处理定位元素时的同步。试试这个:

    public static void expWait_elementclick(WebDriver driver,By by){        
        try {
            (new WebDriverWait(driver, 10)).until(ExpectedConditions.elementToBeClickable(by));
            driver.findElement(by).click();
        } catch (StaleElementReferenceException  ser) {
            // TODO Auto-generated catch block
            driver.findElement(by).click();
        }
    }
    
    
    public static void expWait_elementlocated(WebDriver driver,By by){
        try {
            (new WebDriverWait(driver, 10)).until(ExpectedConditions.presenceOfElementLocated(by));
            driver.findElement(by).click();
        } catch (StaleElementReferenceException  ser) {
            // TODO Auto-generated catch block
            driver.findElement(by).click();
        }
    }
    

    【讨论】:

      【解决方案3】:

      visibilityOfElementLocatedinvisibilityOfElementLocated 方法返回的类型不同:

      public static ExpectedCondition<Boolean> invisibilityOfElementLocated(final By locator) { ... }
      
      public static ExpectedCondition<WebElement> visibilityOfElementLocated(final By locator) { ... }
      

      应用条件时,第一个返回Boolean,第二个返回WebElement

      所以要让它工作,你需要同时实现:

      public static void waitFor(ExpectedCondition<Boolean> condition,int timeoutSeconds) throws Exception {
          setImplicitWait(0);
          try {
              (new WebDriverWait(driver, timeoutSeconds)).until(condition);
          } finally {
              setImplicitWait(WAIT_REGULAR);
          }
      }
      
      public static WebElement waitFor(ExpectedCondition<WebElement> condition,int timeoutSeconds) throws Exception {
          setImplicitWait(0);
          try {
              return (new WebDriverWait(driver, timeoutSeconds)).until(condition);
          } finally {
              setImplicitWait(WAIT_REGULAR);
          }
      }
      

      【讨论】:

      • 方法 waitFor(ExpectedCondition, int) 的擦除与 DriverManager 类型中的另一个方法相同,并且方法 waitFor(ExpectedCondition, int) 的擦除与类型中的另一个方法相同驱动管理器
      【解决方案4】:

      我们的项目中有一个非常好的自定义等待方法,可以轻松适应您可能想要等待的任何条件

      public static void waitForElementToBeVisible(WebDriver driver, int seconds, WebElement element) {
              WebDriverWait wait = (WebDriverWait) new WebDriverWait(driver, seconds)
                      .ignoring(StaleElementReferenceException.class);
              wait.withMessage(ERROR_START + element + ERROR_MIDDLE + seconds + ERROR_END);
              wait.until((ExpectedCondition<Boolean>) webDriver -> element.isDisplayed());
      }
      

      只需将element.isDisplayed() 替换为您想要的任何布尔条件即可。 int 参数是最大值。您想等待条件变为真的超时。

      将它与 Selenium 3.4 一起使用,它就像一个魅力。

      【讨论】:

        【解决方案5】:

        您所问的一个示例如下:

        public WebElement waitFor(WebElement elem, String waitType, long waitInSeconds ) {
        
            Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
                    .withTimeout(waitInSeconds, TimeUnit.SECONDS)
                    .pollingEvery(500, TimeUnit.MILLISECONDS)
                    .ignoring(NoSuchElementException.class);
        
            try{
                switch(waitType) 
                {
                case "elementToBeClickable":
                    wait.until(ExpectedConditions.elementToBeClickable(elem));
                    break;
        
                case "visibilityOf":
                    wait.until(ExpectedConditions.visibilityOf(elem));
                    break;
        
                case "elementToBeSelected":
                    wait.until(ExpectedConditions.elementToBeSelected(elem));
                    break;
        
                default:
                    wait.until(ExpectedConditions.visibilityOf(elem));
                    break;
        
                }
        
            }
            catch(TimeoutException e) {
        
                e.printStackTrace();
        
            }
        
            return elem;
        }
        

        类似地,如果ExpectedCondition 作用于By 或需要额外的参数 这可以根据需要更改。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-07-14
          • 1970-01-01
          • 1970-01-01
          • 2011-02-19
          • 1970-01-01
          相关资源
          最近更新 更多