当前位置: 首页 > 知识库问答 >
问题:

线睡眠有效,但隐式等待、webdriverwait和fluent等待无效?

法浩壤
2023-03-14
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 I get 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));
            }

        });

这将找到combobox,但再次对combobox执行任何操作将导致NoTouchElement或statestate异常。所以我也尝试了从combobox中选择值:

    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;
            }

        });

这超时和doesnot工作!

我如何才能使这项工作,为什么它不工作和线程。睡眠工作。为什么使用线程。睡眠习惯不好?

共有2个答案

长孙沈义
2023-03-14

线睡眠是一种糟糕的做法,因为你使用的是硬编码等待。即使元素在1秒内出现,您也不必再等待3秒。或者,假设元素在10秒后出现。等待4秒钟,之后会出现一个异常,即不存在这样的元素。因此,使用更可靠的预期条件。线睡眠不可靠。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);
亢仰岳
2023-03-14

我将尝试使用ExpectedConditions类中的一些现有检查来验证我返回到“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时,Fluentetc似乎会重试,因此如果您获得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配置中隐式等待和显式等待时间之间的竞争条件。我还没有做过证明这种情况的测试,但这是我目前的理论...

睡眠

  1. 执行任务以刷新dom
  2. 睡眠--dom刷新期间
  3. 从刷新dom重新请求对象
  4. 测试按预期继续

显式等待

  1. 执行任务刷新dom
  2. 显式等待触发(10秒),抓取dom并尝试获取元素(隐式等待30秒)
  3. 多姆刷新
  4. 显式等待在10秒后结束。它只尝试了一次针对原始DOM解析对象
  5. 测试失败

显式等待

  1. 执行任务以刷新dom
  2. 显式等待触发器(30秒),获取dom并尝试获取元素(隐式等待10秒)
  3. Dom刷新
  4. 10秒后,第一个请求失败,dom刷新
  5. 显式等待尝试获取元素,并成功
  6. 测试继续

基于这个假设,我最近没有看到这个问题。我让隐式等待值可供测试访问,现在我有了一些东西,可以根据我要执行的重试次数来计算时间范围。

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

关于线程的使用和可靠性,我完全同意维诺的观点。睡眠,这是不可靠的,如果在一系列测试中出现得太频繁,可能会造成浪费。最好有一个能够尽快响应并解释类型良好且有意义的异常的机制。

祝你好运。

 类似资料:
  • 因此,我理解流畅而明确的等待,但过去我永远无法让隐含的语句起作用。我设法不使用显式词来处理它们,但我随后设计了一个相当简单的测试,但它只适用于线程。睡觉,我绝对讨厌这种方法,并试图不惜一切代价避免它。所以我再次尝试隐式等待函数。。。失败 下面的代码带有线程。睡眠按计划进行,非常好 但当我最终尝试使用隐式(如下面)时,它就不起作用了。我确保在声明驱动程序之后立即声明一次(在本例中为)。考试会在课前的

  • 这里的要点是了解实现等待循环的更有效的解决方案,该循环在每次迭代时轮询条件。通过高效,我的意思是“有效的CPU调度”。 我知道代码中使用的等待条件不是“wakeOne”/“wakeAll”指令中使用的“真正的等待条件”,但我想知道对CPU来说,使用假等待条件是否比睡眠更有效。 这里有2个代码片段,它们做同样的事情:等待某些事情发生。这段代码用于工作线程池。因此,当一个线程等待时,其他线程(或其他一

  • 我正在编写一个基于await/sleep范式的网络绑定应用程序。 我更喜欢这样一个答案,不创建任何额外的线程

  • 我如何用一个显式的替换这个隐式的等待呢? driver=新ChromeDriver(功能); driver.manage().DeleteAllCookies();

  • 我正在使用Ruby和selenium webdriver gem创建一个web爬行/抓取脚本。我几乎完成了这个项目,但在某个点上卡住了,我正在抓取的站点用于对服务器的页面调用并显示一个字符串,问题是它显示了50%的时间,而不是100%。所以我需要循环get函数,直到它显示字符串。 我使用了隐式 我需要的是 好吧,我可以使用正常的睡眠10并且工作正常,但如果调用首先返回字符串,这是浪费时间

  • 我想实现这样的事情:用户按下登录按钮,然后标签显示:连接。 0.5秒时间间隔 连接... 0.5秒时间间隔 连接... 等 只是一种视觉效果,表明“引擎盖下”确实发生了什么。 我所得到的并不是我所期望的。我点击按钮,等待1.5秒,然后我得到了“连接…”,缺少前面的两个步骤。 首先,我的类 还有我的class