Thread.sleep工作,但隐式等待,webdriverwait和流利的等待不?

时间:2015-10-06 19:05:23

标签: java selenium-webdriver wait

driver.findElement(By.xpath(sOptionPath)).click();  //this option button changes contents of page   
Thread.sleep(4000);
WebElement combo=driver.findElement(By.xpath(sXpath));
Select dropdownvalue = new Select(combo);
        dropdownvalue.selectByVisibleText(sText);

以上代码工作正常,但如果我使用wait而不是thread.sleep,我会收到StaleElementReferenceException异常。 这是我使用的流利等待:

    Wait<WebDriver> newwait=new FluentWait<WebDriver>(driver).withTimeout(10, TimeUnit.SECONDS).pollingEvery(1, TimeUnit.SECONDS).ignoring(StaleElementReferenceException.class);

        WebElement combo=newwait.until(new ExpectedCondition<WebElement>(){
            @Override
            public WebElement apply(WebDriver driver) {
                return driver.findElement(By.xpath(sXpath));
            }

        });

这找到了组合框,但是再次对组合框执行任何操作都会产生NoSuchElement或statestate异常。所以我也试过这个从组合框中选择值:

    Wait<WebElement> elwait=new FluentWait<WebElement>(combo).withTimeout(10, TimeUnit.SECONDS).pollingEvery(1, TimeUnit.SECONDS).ignoring(StaleElementReferenceException.class,NoSuchElementException.class);

        Boolean a=elwait.until(new Function<WebElement,Boolean>(){
            @Override
            public Boolean apply(WebElement arg0) {
                Select dropdownvalue = new Select(arg0);
                dropdownvalue.selectByVisibleText(sText);
                return true;
            }

        });

此超时并不起作用!

我怎样才能完成这项工作?为什么它不起作用并且thread.sleep正常工作。为什么使用Thread.sleep是一种不好的做法?

2 个答案:

答案 0 :(得分:1)

我会尝试使用ExpectedCondtions类中的一些现有检查验证我返回'combo'的对象是不是陈旧的。

   Wait<WebDriver> newwait=new FluentWait<WebDriver>(driver).withTimeout(10, TimeUnit.SECONDS).pollingEvery(1, TimeUnit.SECONDS).ignoring(StaleElementReferenceException.class);

        WebElement combo=newwait.until(new ExpectedCondition<WebElement>(){
            @Override
            public WebElement apply(WebDriver driver) {
                WebElement found = driver.findElement(By.xpath(sXpath));
                if (ExpectedConditions.stalenessOf(found).apply(driver)) {
                    return null;
                }
                return found;
            }

        });

我正在使用版本2.47.2,并且当从委托函数返回null时,FluentWait似乎重试,所以如果你得到StaleElementException,我希望这会重试。

 public <V> V until(Function<? super T, V> isTrue) {
    long end = clock.laterBy(timeout.in(MILLISECONDS));
    Throwable lastException = null;
    while (true) {
      try {
        V value = isTrue.apply(input);
        if (value != null && Boolean.class.equals(value.getClass())) {
          if (Boolean.TRUE.equals(value)) {
            return value;
          }
        } else if (value != null) {
          return value;
        }
      } catch (Throwable e) {
        lastException = propagateIfNotIngored(e);
      }

      // Check the timeout after evaluating the function to ensure conditions
      // with a zero timeout can succeed.
      if (!clock.isNowBefore(end)) {
        String toAppend = message == null ?
            " waiting for " + isTrue.toString() : ": " + message;

        String timeoutMessage = String.format("Timed out after %d seconds%s",
            timeout.in(SECONDS), toAppend);
        throw timeoutException(timeoutMessage, lastException);
      }

      try {
        sleeper.sleep(interval);
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw new WebDriverException(e);
      }
    }

我在我的一个测试中看到了类似的东西,它花了我一段时间,但我终于得出结论,在我的情况下,WebDriver配置中的隐式等待和显式等待时间之间存在竞争条件。我还没有做过证明这个案例的测试,但这是我现在的理论......

SLEEP

  1. 执行任务以刷新dom
  2. 睡觉 - dom刷新期间
  3. 从刷新dom
  4. 重新请求对象
  5. 测试按预期继续进行。
  6. 显式等待&lt; =隐含等待

    1. 执行任务以刷新dom
    2. 显式等待触发器(10秒),抓住dom并尝试获取元素(隐式等待30秒)
    3. Dom Refreshes
    4. 显式等待在10秒后结束。它只尝试过一次就原始DOM解析对象
    5. 测试失败
    6. 显式等待&gt;隐含等待

      1. 执行任务以刷新dom
      2. 显式等待触发器(30秒),抓住dom并尝试获取元素(隐式等待10秒)
      3. Dom Refreshes
      4. 10秒后,第一个请求失败,dom刷新
      5. 显式等待尝试获取元素,并且成功
      6. 测试继续。
      7. 根据这个假设,我最近没有看到这个问题。我让我的测试可以访问隐式等待值,现在我根据我想要执行的重试次数来计算时间范围。

        private final WebElement explicitWait(int retries, Predicate<Boolean> test) {
                WebDriverWait wait = new WebDriverWait(driver, retries * getImplicitWait());
                return wait.until(test);
        }
        

        我完全同意Vinoth关于Thread.sleep的使用和可靠性,它是不可靠的,如果它在一大套测试中经常发生,可能会浪费。最好有一个能够尽快响应的机制,并考虑到类型良好且有意义的异常。

        最好的运气。

答案 1 :(得分:0)

Thread.sleep是一种不好的做法,因为你正在使用硬编码等待。即使元素出现在1秒内,你也会不经意地等待3秒钟。或者,让我们说这个元素在10秒后出现。等待4秒钟,之后您将获得一个不存在此类元素的异常。因此,使用更可靠的预期条件。 Thread.sleep不可靠。 https://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/ui/ExpectedConditions.html

WebDriverWait wait = new WebDriverWait(driver, timeout);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath(sXpath)));

WebElement combo=driver.findElement(By.xpath(sXpath));
Select dropdownvalue = new Select(combo);
dropdownvalue.selectByVisibleText(sText);