如果使用以下代码检查缺席元素:
// ...
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
try {
driver.findElement(By.cssSelector("td.name"));
} catch (NoSuchElementException e) {
// here you go, element not found
}
你得到了正确的结果,但由于findElement
方法阻止了隐式等待,因此运行时间总是30秒。
有没有办法避免这种行为,同时保持隐含的等待?
<EDIT>
测试将由非开发人员通过Selenium IDE生成,因此我需要一种解决方案,使他们的工作尽可能简单(保持等待隐含!)。的 </EDIT>
谢谢,
马
答案 0 :(得分:3)
即使元素不再存在,上述方法也会等待所提供的时间。我编写了自己的方法,等待元素可见而不存在。他们为我工作。他们在这里:
public void waitUntilElementExists(By by, int waitSeconds,
int noOfRetries) {
getDriver().manage().timeouts().implicitlyWait(waitSeconds, TimeUnit.SECONDS);
boolean foundElement = false;
for (int i = 0; i < noOfRetries; i++)
try {
getDriver().findElement(by);
foundElement = true;
break;
} catch (Exception e) {
}
assertTrue("The searched element was not found after " + noOfRetries * waitSeconds + " seconds!", foundElement);
}
public void waitUntilElementDoesntExist(By by, int waitSeconds,
int noOfRetries) {
getDriver().manage().timeouts().implicitlyWait(waitSeconds, TimeUnit.SECONDS);
boolean elementDisappeared = false;
for (int i = 0; i < noOfRetries; i++)
try {
getDriver().findElement(by);
waitABit(1000 * waitSeconds);
} catch (Exception e) {
elementDisappeared = true;
break;
}
assertTrue("The searched element did not disappear after " + noOfRetries * waitSeconds + " seconds!", elementDisappeared);
}
答案 1 :(得分:2)
您可以使用xpath选择器执行此操作。找到你知道应该在那之前的元素,然后使用&#34; follow-sibling&#34;获得下一个元素。类似的东西:
//td.previous/following-sibling::td
然后检查它是否还没有返回&#34; name&#34;一。当然,这只有在有另一个&#34; td&#34;元件。
就我个人而言,我很想放弃隐含的等待,只需在需要时等待。
private WebElement cssWait( final String css )
{
return new WebDriverWait( driver, 30 ).until( new ExpectedCondition< WebElement >()
{
@Override
public WebElement apply( WebDriver d )
{
return d.findElement( By.cssSelector( css ) );
}
} );
}
答案 2 :(得分:2)
我没有设置超时,而是使用2.25中引入的fluentWait。
public void waitForElement(WebDriver driver, final String xpath)
{
//Set up fluentWait to wait for 35 seconds polling every 1
Wait<WebDriver> fluentWait = new FluentWait<WebDriver>(driver)
.withTimeout(35, TimeUnit.SECONDS)
.pollingEvery(1, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
WebElement element;
//Look for element, if not found start fluentWait
try
{
element = driver.findElement(By.xpath(xpath));
}
catch (WebDriverException e)
{
logger.info("[getElementByXpath] Element not initially found. Starting fluentWait ["+xpath+"]");
try
{
element = fluentWait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver d) {
return d.findElement(By.xpath(xpath));
}
});
}
catch (WebDriverException f)
{
logger.info("[getElementByXpath] FluentWait findElement threw exception:\n\n" + f +"\n\n");
throw new WebDriverException("Unable to find element ["+xpath+"]");
}
}
//Once we've found the element wait for element to become visible
fluentWait.until(ExpectedConditions.visibilityOf(element));
}
如果您要将方法转换为此类方法,则可以删除driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
,以便“不”立即找到元素。
希望这有帮助!
答案 3 :(得分:0)
您需要使用findElements
而不是findElement
public static ExpectedCondition<Boolean> elementCountIs(final By sel, final int count) {
return new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver driver) {
return driver.findElements(sel).size() == count;
}
};
}
然后您可以设置Falkenfighter所描述的FluentWait
对象,并且:
fluentWait.until(elementCountIs(By.cssSelector("td.name"), 0);
答案 4 :(得分:0)
您必须暂时更新ImplicitWait,并在完成后重置它。
这是我们处理这种情况的方式 - 保存当前默认值,暂时更新ImplicitWait,然后再更改回默认值。
这是基于Mozilla的建议,这是他们如何处理这种情况,你期望不存在的东西:
https://blog.mozilla.org/webqa/2012/07/12/webdrivers-implicit-wait-and-deleting-elements/
public bool ElementExists(By by, int waitMilliseconds)
{
var defaultWebDriverTimeout = 30000;// Get default timeout that you're using
WebDriver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromMilliseconds(waitMilliseconds));
try
{
WebDriver.FindElement(by); //Note could be FindElements instead, but this is quicker
return true;
}
catch (NoSuchElementException)
{
return false;
}
finally
{
WebDriver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromMilliseconds(defaultWebDriverTimeout));
}
}
答案 5 :(得分:0)
implicit
等待时间优先于显式等待。
如果您的implicit
时间是30秒,那么您运行的任何查找都将至少30秒,以防该元素不存在。
您可以做的是操纵框架上的implicit
等待时间,但不确定如何使用IDE,我从未使用它。
我创建了一个自定义方法,返回带有结果的boolean
。
输入是 WebDriver(CSS,xpath等)支持的任何按定位器 。
或者,您可以根据需要进行修改。
它有助于使我的代码更清晰,更快捷。我希望它也可以帮助其他人。
默认pooling
为500 Millis,但可以在wait
对象上进行更改。
public boolean isElementNotPresent(final By locator) {
boolean result = false;
// use your custom timeout here
long timeout = ConfigurationProvider.getWebDriverWaitTimeout();
// log4j used
msg = "isElementNotPresent: " + locator;
LOG.info(msg);
Wait<WebDriver> wait = new FluentWait<WebDriver>(
getDriver()).withTimeout(timeout, TimeUnit.SECONDS);
try {
result = wait.until(new Function<WebDriver, Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
return driver.findElements(locator).size() == 0;
}
});
} catch (TimeoutException e) {
msg = String.format("Element remained visible after %.2f seconds",
((float) timeout / 1000));
LOG.debug(msg);
} catch (Exception e) {
msg = "Exception at isElementNotPresent()\n" + e.getMessage();
// I use jUnit to fail my test
Assert.fail(msg);
}
return result;
};