【问题标题】:Temporarily bypassing implicit waits with WebDriver使用 WebDriver 暂时绕过隐式等待
【发布时间】:2012-06-17 13:57:09
【问题描述】:

当使用隐式等待时,as advised here,我仍然有时想要断言元素的立即不可见或不存在。

换句话说,我知道应该隐藏一些元素,并且希望我的测试快速做出该断言,而无需花费几秒钟,因为(其他有用的)隐式等等。

我尝试过的一件事是这样的辅助方法:

// NB: doesn't seem to do what I want
private boolean isElementHiddenNow(String id) {
    WebDriverWait zeroWait = new WebDriverWait(driver, 0);
    ExpectedCondition<Boolean> c = invisibilityOfElementLocated(By.id(id));
    try {
        zeroWait.until(c);
        return true;
    } catch (TimeoutException e) {
        return false;
    }
}

但在上面的代码中,对until() 的调用只在隐式等待时间过去后返回,也就是说,它并没有达到我想要的效果。

这是迄今为止我发现的唯一可行的方法:

@Test
public void checkThatSomethingIsNotVisible()  {
    turnOffImplicitWaits();
    // ... the actual test
    turnOnImplicitWaits();
}

...例如在哪里turnOffImplicitWaits() 是普通 Selenium 超类的助手:

protected void turnOffImplicitWaits() {
    driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
}

但我认为这不是很优雅。 有什么更简洁的方法可以偶尔绕过隐式等待吗?

【问题讨论】:

  • 我不相信接口定义的任何东西都可以满足您的需求。我唯一能想到的就是调用 findElements 而不是 findElement。但我也不确定是否会绕过隐式等待。
  • @MikeKwan 不,findElements() 也会在至少找到一个元素后尝试等待并返回。
  • 对于 lambdas public void bypassImplicitWaits(Bypass bypass) { turnOffImplicitWaits(); bypass.do(); turnOnImplicitWaits(); } 来说是一个很好的案例@

标签: java selenium selenium-webdriver webdriver wait


【解决方案1】:

鉴于 Selenium 似乎不能直接提供我想要的东西(基于 Mike Kwan 和 Slanec 所说的),这个简单的辅助方法是我现在采用的方法:

protected boolean isElementHiddenNow(String id) {
    turnOffImplicitWaits();
    boolean result = ExpectedConditions.invisibilityOfElementLocated(By.id(id)).apply(driver);
    turnOnImplicitWaits();
    return result;
}

private void turnOffImplicitWaits() {
    driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
}

private void turnOnImplicitWaits() {
    driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}

如果元素被隐藏或根本不存在,该方法返回true;如果可见,则返回 false。无论哪种方式,检查都会立即完成。

使用上述方法至少比通过调用turnOffImplicitWaits()turnOnImplicitWaits() 乱扔测试用例本身要干净得多。

有关相同方法的微调版本,另请参阅以下答案:

【讨论】:

  • 如何开启隐式等待?
  • @JeffMay:类似于driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);。参见例如this answer.
  • 在示例中使用 By 作为参数,这样会更容易并且可以用于所有人:)
  • 有人知道如何在 Python 中复制这一行:driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS)?我在文档中找不到它
  • 没关系,您可以按照最初设置的方式设置隐式等待时间。
【解决方案2】:

我还建议将参数更改为“By”定位器,以便在查找元素时更加灵活。

protected boolean isElementHiddenNow(By locator) {
    turnOffImplicitWaits();
    boolean result = false;
    try {
       result = ExpectedConditions.invisibilityOfElementLocated(locator).apply(driver);
    }
    finally {
       turnOnImplicitWaits();
    }
    return result;
}

这样,如果需要,您可以通过 css 进行搜索,而不仅仅是 id:

By PartLinkLocator = By.cssSelector("div.search-result div.row a");

'当然,您的定位器可能应该设计为只返回一个元素(与我快速抓取的“By”示例不同,它返回行的 css 表中的所有部分链接......)所以,一个“id”示例看起来像

By usernameLocator = By.id("inputEmail");
myResult = isElementHiddenNow(usernameLocator);

【讨论】:

  • 绝对是 try/finally 是要走的路。
【解决方案3】:

我的实现:

using (driver.NoImplicitWait())
{
    ....
}

带扩展方法:

public static NoImplicitWait NoImplicitWait(this IWebDriver driver)
{
    return new NoImplicitWait(driver);
}

和类:

public sealed class NoImplicitWait : IDisposable
{
    private readonly IWebDriver _driver;

    public NoImplicitWait(IWebDriver driver)
    {
        _driver = driver;
        _driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(0));
    }

    public void Dispose()
    {
        _driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(30));
    }
}

【讨论】:

    【解决方案4】:

    @Jonic's answer 帮助了我,但是我会添加一个 try { } finally { } 并在 finally 块中调用 turnOnImplicitWaits() 以确保它始终重新打开。

    protected boolean isElementHiddenNow(String id) {
        turnOffImplicitWaits();
        boolean result = false;
        try {
           result = ExpectedConditions.invisibilityOfElementLocated(By.id(id)).apply(driver);
        }
        finally {
           turnOnImplicitWaits();
        }
        return result;
    }
    

    【讨论】:

      【解决方案5】:

      我的方法是完全绕过隐式等待,并在我现在默认使用的 findElement()findElements() 方法中重新实现它(添加可见性检查等)。这样,当我想立即检查某些内容时,我可以调用原始的 WebDriver 方法,这当然不会等待。

      【讨论】:

      • 如何在不使用implicitWait 选项的情况下进行等待?您是否只是在某种循环中实现了 try/catch 并每隔几秒轮询一次元素,直到达到某个阈值?
      • @AndyPerfect 是的,通常的(try-catch,重试或超时)方法具有一些基本的附加功能:可见性,禁用元素,突出显示找到的元素,页面未真正加载的解决方法(重新开始StaleElementReference),暂时也用于thisthis 错误。
      【解决方案6】:

      在大量依赖隐式等待思维方式的现有代码中,在没有 CSS 的情况下,我找到了解决这类事情的方法,用 Jsoup 补充它,然后用 Jsoup 继续:

      # this is straightforward Scala... put the types and it is Java.
      val innerHtml = seleniumWebElementFatherInstance.getAttribute("innerHTML")
      val jsoupElements = Jsoup.parse(innerHtml).select("div.your.css.selector")
      

      【讨论】:

        猜你喜欢
        • 2012-05-11
        • 2018-01-24
        • 2013-11-26
        • 1970-01-01
        • 2017-04-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多