![](/img/trans.png)
[英]Selenium WebDriver: Check if element present or not for a while loop?
[英]Selenium 2 - How to check if element not present while implicitly waiting?
如果使用以下代码检查缺少的元素:
// ...
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
try {
driver.findElement(By.cssSelector("td.name"));
} catch (NoSuchElementException e) {
// here you go, element not found
}
你得到了正确的结果,但是运行时间总是30秒,因为隐式等待上的findElement
方法阻塞。
有没有办法避免这种行为,同时保持隐含的等待?
<EDIT>
测试将由非开发人员通过Selenium IDE生成,因此我需要一种解决方案,使他们的工作尽可能简单(保持等待隐含!)。 </EDIT>
谢谢,
马尔科
即使元素不再存在,上述方法也会等待所提供的时间量。 我编写了自己的方法,等待元素可见而不存在。 他们为我工作。 他们来了:
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);
}
您可以使用xpath选择器来完成它。 找到你知道应该在那之前的元素,然后使用“follow-sibling”来获取下一个元素。 就像是:
//td.previous/following-sibling::td
然后检查它是否还没有返回“名称”。 当然,这只有在有另一个“td”元素时才有效。
就个人而言,我很想放弃隐含的等待,只需要在需要时等待。
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.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);
允许你'不'立即找到一个元素。
希望这可以帮助!
你需要一个像这样的函数,它使用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;
}
};
}
然后你可以按照FluentWait
描述设置一个FluentWait
对象:
fluentWait.until(elementCountIs(By.cssSelector("td.name"), 0);
您必须暂时更新ImplicitWait,并在完成后重置它。
这是我们处理这种情况的方式 - 保存当前默认值,暂时更新ImplicitWait,然后再更改回默认值。
这是基于Mozilla的建议,这是他们如何处理你期望某些东西不存在的情况: https : //blog.mozilla.org/webqa/2012/07/12/webdrivers-implicit-wait-and-删除元素/
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));
}
}
你不能。 implicit
等待时间优先于显式等待。 如果您的implicit
时间是30秒,则在元素不存在的情况下,您运行的任何查找将至少为30秒。 你可以做的是操纵你的框架上的implicit
等待时间,但不知道如何与IDE,我从来没有使用它。
我创建了一个自定义方法,返回带有结果的boolean
。 输入是WebDriver支持的任何By定位器 (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;
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.