24

当使用隐式等待时,正如这里所建议的那样,我有时仍然想断言元素的立即不可见或不存在。

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

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

// 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();
}

... 其中 egturnOffImplicitWaits()是常见 Selenium 超类中的助手:

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

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

4

6 回答 6

23

鉴于 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() and更干净turnOnImplicitWaits()

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

于 2012-06-15T09:00:19.307 回答
7

我还建议将参数更改为“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);
于 2014-07-28T18:32:40.503 回答
6

我的实现:

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));
    }
}
于 2016-03-10T11:03:10.423 回答
3

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

protected boolean isElementHiddenNow(String id) {
    turnOffImplicitWaits();
    boolean result = false;
    try {
       result = ExpectedConditions.invisibilityOfElementLocated(By.id(id)).apply(driver);
    }
    finally {
       turnOnImplicitWaits();
    }
    return result;
}
于 2014-04-29T08:17:23.303 回答
1

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

于 2012-06-14T15:24:22.583 回答
0

在大量依赖隐式等待思维方式的现有代码中,并且没有 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")
于 2017-10-01T12:59:28.937 回答