I have written few test cases in Selenium WebDriver using Java and execute them on grid (hub and multiple nodes). I have noticed that a few test cases fail due to NoSuchElementException
. What is the best and robust way to avoid NoSuchElementException
and ensure the element is always found?
问题:
回答1:
You can never be sure that element will be found, actually this is purpose of functional tests - to tell you if anything changed on your page. But one thing which definitely helps is to add waits for the elements which are often causing NoSuchElementException
like
WebDriverWait wait = new WebDriverWait(webDriver, timeoutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id<locator>));
回答2:
I completely agree to Petr Mensik above. The matter you can never say whether element is present. You should clearly understand why when it happens. From my experience I should say that it happens due to the following reasons:
- 1) The page is still being rendered and you've already finished your element search and obtain no element exception.
- 2) The second reason is AJAX has not returned yet and you've already
obtain
NoSuchElementException
- 3) The third is most obvious: The element is really not on the page whenever.
so the most robust IMHO way to handle all these three conditions using one function call is to use fluentWait
as Amith003 suggested.
so the code be the following:
let ur element has the locator:
String elLocXpath= "..blablabla";
WebElement myButton= fluentWait(By.xpath(elLocXpath));
myButton.click();
public WebElement fluentWait(final By locator){
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(org.openqa.selenium.NoSuchElementException.class);
WebElement foo = wait.until(
new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(locator);
}
}
);
return foo;
};
Also if your purpose is robust code wrap fluentWait()
with a try{} catch{}
block.
Also don't forget about
public boolean isElementPresent(By selector)
{
return driver.findElements(selector).size()>0;
}
that is also useful.
So to conclude all the mentioned if you want to avoid NoElement
exception just handle it properly as nobody can ensure in the element presence on the page.
Hope now it is more clear to you. Regards
回答3:
you can also use FluentWait
,
Each FluentWait
instance defines the maximum amount of time to wait for a condition, as well as the frequency with which to check the condition.
Furthermore, the user may configure the wait to ignore specific types of exceptions whilst waiting, such as NoSuchElementExceptions
when searching for an element on the page.
// Waiting 30 seconds for an element to be present on the page, checking
// for its presence once every 5 seconds.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(By.id("foo"));
}
});
Click here for more info
回答4:
WebDriverWait wait = new WebDriverWait(webDriver, timeoutInSeconds);
wait.until(ExpectedConditions.elementToBeClickable(By.id<locator>));
elementToBeClickable waits for Enable and Visible of an Element
回答5:
public WebElement fluientWaitforElement(WebElement element, int timoutSec, int pollingSec) {
FluentWait<WebDriver> fWait = new FluentWait<WebDriver>(driver).withTimeout(timoutSec, TimeUnit.SECONDS)
.pollingEvery(pollingSec, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class, TimeoutException.class);
for (int i = 0; i < 2; i++) {
try {
//fWait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//*[@id='reportmanager-wrapper']/div[1]/div[2]/ul/li/span[3]/i[@data-original--title='We are processing through trillions of data events, this insight may take more than 15 minutes to complete.']")));
fWait.until(ExpectedConditions.visibilityOf(element));
fWait.until(ExpectedConditions.elementToBeClickable(element));
}
catch (Exception e) {
System.out.println("Element Not found trying again - " + element.toString().substring(70));
e.printStackTrace();
}
}
return element;
}
回答6:
I usually use this line in the main function
public static void main(String[] args) throws ParseException {
driver= new ChromeDriver();
driver.manage().window().maximize();
**driver.manage().timeouts().implicitlyWait(30,TimeUnit.SECONDS);**
Hope this helps.
回答7:
We can apply below codes to remove this exception condition
By applying WebDriverWait, webdriver object wait for a specific time (in second) of an element for its visibility.
WebDriverWait wait = new WebDriverWait(driver, 10); wait.until(ExpectedConditions.visibilityOf(link));
We can handle NoSuchElementException through try-catch block inside Generic method
public boolean isElementPresent(By by) { boolean isPresent = true; try { driver.findElement(by); } catch (NoSuchElementException e) { isPresent = false; } return isPresent }
http://selenium-code.blogspot.in/2017/08/selenium-exception-nosuchelementexcepti.html