I'm trying to use an element for testing and I want to continue the test if the element even couldn't be found.
I used NoSuchElementException for this part of my codes.
Here is what I've tried before:
try {
WebElement site_width_full_width = wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector("label[for=site_width-full_width]")));
site_width_full_width.click();
Thread.sleep(1000);
System.out.println("FullWidth Label Found!");
} catch (NoSuchElementException e) {
System.out.println("FullWidth Label not found!");
System.out.println(e);
}
But when the element isn't available it can't be thrown into the NoSuchElementException and all test breaks and fails.
What's the solution and how could I continue the test when the element isn't available.
Thanks in advance.
You might be getting the exception of a different derived class type. You can catch it using the parent class 'Exception' and then further drill down the exact exception type.
try using;
try
{
WebElement site_width_full_width = wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector("label[for=site_width-full_width]")));
site_width_full_width.click();
Thread.sleep(1000);
System.out.println("FullWidth Label Found!");
}
catch (Exception e)
{
if (e instanceof NoSuchElementException)
{
System.out.println("FullWidth Label not found!");
System.out.println(e);
}
else
{
System.out.println("Unexpected exception!");
System.out.println(e);
}
}
Hope this helps.
You can try with its parent classes like Throwable or Exception in catch block. In my case, I am Throwable in catch block which works as expected
You are catching a NoSuchElementException, but an explicit wait throws a TimeoutException if nothing is found. To get what you have working you should modify your code to do the following:
try {
WebElement site_width_full_width = wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector("label[for=site_width-full_width]")
));
site_width_full_width.click();
System.out.println("FullWidth Label Found!");
} catch (NoSuchElementException | TimeoutException e) {
System.out.println("FullWidth Label not found!");
System.out.println(e);
}
However using Try/Catch for execution flow is generally a code anti-pattern. You would be much better off doing something like this:
List<WebElement> site_width_full_width =
driver.findElements(By.cssSelector("label[for=site_width-full_width]"));
if (site_width_full_width.size() > 0) {
System.out.println("FullWidth Label Found!");
site_width_full_width.get(0).click();
} else {
System.out.println("FullWidth Label not found!");
}
Webdriver already provide the way to deal this problem in much simpler way. you can use following way
WebDriverWait wait= new WebDriverWait(driver, TimeSpan.FromSeconds(120));
wait.IgnoreExceptionTypes(typeof(NoSuchElementException), typeof(ElementNotVisibleException));
WebElement site_width_full_width = wait.until(
ExpectedConditions.visibilityOfElementLocated(
By.cssSelector("label[for=site_width-full_width]")));
site_width_full_width.click();
Thread.sleep(1000);
System.out.println("FullWidth Label Found!");
Note : You can add all types of exception need to be ignored.
Related
private WebElement findElementByXpath(WebDriver driver, String xpath) throws WebElementNotFoundException, HopelessAccountException {
WebElement element = null;
try {
element = new WebDriverWait(driver, Duration.ofSeconds(dirationInSeconds))
.until(ExpectedConditions.elementToBeClickable(By.xpath(xpath)));
} catch (TimeoutException timeoutException) {
loggingService.timeMark("findElementByXpath", "TimeoutException");
throw new WebElementNotFoundException();
} catch (UnhandledAlertException alertException) {
loggingService.timeMark("findElementByXpath", "alertException");
final String LIMITS_EXHAUSTED_MESSAGE = "Not enough limits!";
String message = alertException.getMessage();
if (message.contains(LIMITS_EXHAUSTED_MESSAGE)){
throw new HopelessAccountException(); // Attention.
}
} catch (Exception e) {
// Mustn't be here.
loggingService.timeMark("findElementByXpath", e.getMessage());
driver.quit();
System.out.println("QUIT!");
System.exit(0);
}
loggingService.timeMark("findElementByXpath", "end. Xpath: " + xpath);
return element;
}
Please, have a look at the line that I commented as "Attention".
I have caught the exception where there is not enough limits any more. And I throw the exception that the account is hopeless.
But it is immediately caught by just after the next few lines. Namely where I commented "Mustn't be here".
I would like to preserve this catching any exception. At least for debugging purpose.
Could you help me understand whether I can both throw HopelessAccountException and preserve the "catch Exception" block?
You can always modify your Exception block to rethrow e if it is an instance of HopelessAccountException:
} catch (Exception e) {
if (e instanceof HopelessAccountException) throw e; // preserves original stack trace
// Mustn't be here.
loggingService.timeMark("findElementByXpath", e.getMessage());
driver.quit();
System.out.println("QUIT!");
System.exit(0);
}
However as #fishinear indicates, in your posted code the Exception block would not be reached as a result of the throw of throw new HopelessAccountException() - if your actual code looked more like:
try {
try {
System.out.println("In A()");
// do something to cause an exception E3 (e.g. UnhandledAlertException)
throw new E3();
} catch (E3 e3) { // UnhandledAlertException
System.out.println("In E3 catch");
throw new E1(); // HopelessAccountException
}
} catch (Exception e) {
System.out.println("In Exception catch");
if (e instanceof E1) throw e; // rethrow HopelessAccountException
System.out.println("e: "+e);
}
Then the test-and-rethrow is possible.
Then when you rip out your debugging "try block" your code would behave the same (for the HopelessAcountException).
in your code that calls findElementByXpath(…) you could catch the broad Exception type there. This means in your findElementByXpath(…) method you could just handle the known exceptions and anything else could be captured in calling code
OS: Windows 7 32bit
ChromeDriver version: 2.30
Selenium Webdriver version: 3.4.0
Java 8
I've tried a few different ways to clean this code up and not have to repeat the same try/catch blocks. I'm trying to check that various elements are present on a page I'm testing. I can gracefully report to the console and this code does work with no problems.
The issue I'm having is with the ungraceful code. Is there a way to nest these try/catch blocks, or put them inside of an if/else loop?
try {
driver.findElement(By.xpath("/html/head/title"));
System.out.println("Title found...");
Thread.sleep(1000);
} catch (NoSuchElementException ex) {
System.out.println("Title NOT FOUND...");
// ex.printStackTrace();
}
try {
driver.findElement(By.xpath("//*[#id='logindiv']"));
System.out.println("Login form found...");
Thread.sleep(1000);
} catch (NoSuchElementException ex) {
System.out.println("Login form NOT FOUND...");
// ex.printStackTrace();
}
try {
driver.findElement(By.id("username"));
System.out.println("'Username' field found...");
Thread.sleep(1000);
} catch (NoSuchElementException ex) {
System.out.println("'Username' form NOT FOUND...");
// ex.printStackTrace();
}
try {
driver.findElement(By.id("password"));
System.out.println("'Password' field found...");
Thread.sleep(1000);
} catch (NoSuchElementException ex) {
System.out.println("'Password' form NOT FOUND...");
// ex.printStackTrace();
}
try {
driver.findElement(By.id("loginSubmit")).getText();
System.out.println("Login button found...");
Thread.sleep(1000);
} catch (NoSuchElementException ex) {
System.out.println("Login button NOT FOUND...");
// ex.printStackTrace();
}
A few things...
I'm a firm believer that exceptions should be exceptional, meaning exceptions shouldn't be used as flow control. This is further supported by the docs,
findElement should not be used to look for non-present elements, use findElements(By) and assert zero length response instead.
so you should replace .findElement() and try-catch with .findElements() and test for empty. See example in #2.
You really should use some Assert library like JUnit, etc. It makes these validations so much easier/cleaner.
This whole thing
try
{
driver.findElement(By.id("username"));
System.out.println("'Username' field found...");
Thread.sleep(1000);
}
catch (NoSuchElementException ex)
{
System.out.println("'Username' form NOT FOUND...");
// ex.printStackTrace();
}
should/could look like
Assert.assertFalse(driver.findElements(By.id("username")).isEmpty(), "Validate Username field exists");
Arguments could be made that it's faster, so on and so forth but... it hurts me to see people use something complicated like an XPath to do no more than locate an element by ID, e.g. By.xpath("//*[#id='logindiv']"). This is so much simpler and easier to read as By.id("logindiv").
You can do some googling to see all the details but Thread.Sleep() is a bad practice and should be avoided. Instead use WebDriverWait. Explore ExpectedConditions to see all what can be waited for and use it liberally. In the cases you posted in your code, I don't see any reason to wait for any of these so that's several seconds of unnecessary wasted time.
Your last example is pulling .getText() but not using it. Since you are just checking that the button exists, you can safely remove the .getText() from the end.
You can try this:
public void checkElementVisibile()throws InterruptedException {
element = driver.findElement(By.xpath("/html/head/title"));
Thread.sleep(1000);
if(isElementVisibile(element))
System.out.println("Title found...");
else
System.out.println("Title not found...");
element = driver.findElement(By.xpath("//*[#id='logindiv']"));
Thread.sleep(1000);
if(isElementVisibile(element))
System.out.println("Login form found...");
else
System.out.println("Login form not found...");
element = driver.findElement(By.id("username"));
Thread.sleep(1000);
if(isElementVisibile(element))
System.out.println("'Username' field found...");
else
System.out.println("'Username' field not found...");
element = driver.findElement(By.id("password"));
Thread.sleep(1000);
if(isElementVisibile(element))
System.out.println("'Password' field found...");
else
System.out.println("'Password' field not found...");
}
public static boolean isElementVisibile(WebElement element){
try {
return element.isDisplayed();
}catch (NoSuchElementException ex)
{
return false;
}
}
My problem is I have customWaitMethods such as:
public void waitForLoading(WebElement loadingElement, WebElement errorElement) {
long timeOut = Long.parseLong(PropertyReader.getInstance().getProperty("DEFAULT_TIME_OUT"));
try {
WebDriverWait wait = new WebDriverWait(DriverFactory.getInstance().getDriver(), timeOut);
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.id(loadingElement.toString())));
if (errorElement.isDisplayed()) {
throw new TestException();
}
} catch (TimeoutException e) {
System.out.println("Timed out after default time out");
} catch (TestException e) {
System.out.println("Unexpected error occurred, environment error");
e.printStackTrace();
}
}
I need some generic customWait methods. I do a search, but several cases need to be handled. Error msg appear -> fail the test. wait for the loading content, and it disappeared, -> check the search result.
How can I extend this code if I would like to check continuously some error_message element appears as well and in this case I would throw an exception? So independently I can handle the timeout exception and the other, error msg?
This sript is failing because of the IF. ErrorElement does not appear on the page, ---> nosuchelementException
You can catch different Exceptions as you see fit. In your case, you want to catch the TimeoutException to handle time outs. Then catch a different type of exception to handle the error message:
public void waitForLoading() {
long timeOut = Long.parseLong(...);
try {
WebDriverWait wait = new WebDriverWait(...);
wait.until(ExpectedConditions.invisibilityOfElementLocated(...));
if (<error-message-appears>) {
throw new CustomErrorMessageAppearedException();
}
} catch (TimeoutException e) {
System.out.println("Timed out after...");
} catch (CustomErrorMessageAppearedException e) {
// handle error message
}
}
The easiest approach I see is:
public void waitForLoading() {
long timeOut = Long.parseLong(PropertyReader.getInstance().getProperty("DEFAULT_TIME_OUT"));
try {
WebDriverWait wait = new WebDriverWait(DriverFactory.getInstance().getDriver(), timeOut);
if (!wait.until(ExpectedConditions.invisibilityOfElementLocated(By.id("wait_element")));)
{
throw new NoSuchElementException();
}
} catch (TimeOutException e) {
System.out.println("Timed out after " + timeOut + "seconds waiting for loading the results.");
}
}
A Robust Try Catch Method to use in WebDriver?
Can someone advice from there experiece whether the following method looks correct in the likely scenario where searching for an element gets timed out or the incorrect locator has been used?
The timeout Exception dosnt seem to be printing my System.out.println after i set the wait to 2seconds and change the locator with the wrong xpath
My Code:
public void clickSupercarsLink() throws Exception {
try {
this.wait.until(ExpectedConditions.elementToBeClickable(link_Supercars)).click();
} catch (TimeoutException e) {
System.out.println("UNABLE TO FIND ELEMENT : Timeout");
} catch (Exception e) {
System.out.println("UNABLE TO FIND ELEMENT : Exception");
throw (e);
}
}
New Code:
public void clickSupercarsLink() throws Exception {
try {
this.wait.until(ExpectedConditions.elementToBeClickable(link_Supercars)).click();
} catch (TimeoutException e) {
System.out.println("Timed out attempting to click on element: <" + link_Supercars.toString() + ">");
} catch (Exception e) {
System.out.println("Unable to click on element: " + "<" + link_Supercars.toString() + ">");
}
}
#Phil I would want you to throw that exception and handle it at high level. In current scenario, if there is a critical exception, your test will method calling your method clickSupercarsLink will not know that there was an exception.
Any way you are throwing exception, why do you have to catch it and do nothing with it then just printing!! This is not why you throw exception right?
public void clickSupercarsLink() throws Exception {
this.wait.until(ExpectedConditions.elementToBeClickable(link_Supercars)).click();
}
I'm having a problem in my script. I'm using Selenium WebDriver to drive a webpage, but i'm getting ElementNotFound exceptions quite regularly. The page takes a second or two to load.
My code is the following:
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(10, TimeUnit.SECONDS)
.pollingEvery(1, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
try
{
WebElement username = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#class='gwt-TextBox']")));
username.sendKeys(usernameParm);
}
catch (Exception e) {
e.printStackTrace();
}
The exception still gets thrown after a second or so. Then if i test it by running the following:
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(10, TimeUnit.SECONDS)
.pollingEvery(1, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
try
{
WebElement username = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#class='gwt-TextBox1']")));
username.sendKeys(usernameParm);
}
catch (Exception e) {
e.printStackTrace();
}
Knowing that TexBox1 doesn't exist, then it throws the same exception. It doesn't appear to be waiting. In the second instance i would expect it to time out, and not throw ElementNotFoundException.
My implementation is probably wrong.
Checkout my post on this topic: https://iamalittletester.wordpress.com/2016/05/11/selenium-how-to-wait-for-an-element-to-be-displayed-not-displayed/. There are code snippets there. Basically my suggestion is not to use FluentWait, but instead:
WebDriverWait wait = new WebDriverWait(driver, TIMEOUT);
ExpectedCondition elementIsDisplayed = new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver arg0) {
try {
webElement.isDisplayed();
return true;
}
catch (NoSuchElementException e ) {
return false;
}
catch (StaleElementReferenceException f) {
return false;
}
}
};
wait.until(elementIsDisplayed);
Define TIMEOUT with whatever timeout value seems ok for you (i believe you said 10 seconds in your initial issue).
Yes, i'm answering my own question. Figured out what the problem was.
I had imported java.lang.util.NoSuchElementException
I had told FluentWait to ignore NoSuchElementException
What was actually being thrown was org.openqa.selenium.NoSuchElementException
Once i changed it, it seems to work just fine.
Before i figured this out, i also implemented this:
for (int i = 0; i< 10; i++){
if (B_Username){
break;
} else {
try {
WebElement username = driver.findElement(By.xpath("//*[#class='gwt-TextBox']"));
B_Username = true;
username.sendKeys(usernameParm);
} catch (NoSuchElementException e) {
System.out.println("Caught exception while locating the username textbox");
System.out.println(i);
try {
Thread.sleep(500);
} catch (InterruptedException ee) {
System.out.println("Somthing happened while the thread was sleeping");
}
}
}
}
which worked fine as well.
Maybe this will help someone else another time.
Thanks to everyone who answered.