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();
}
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
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.");
}
}
Why dosnt my method catch my 'Timeout Exception' and print to console?
public void clickDrivingExperienceButton() throws Exception {
boolean test = this.wait.until(ExpectedConditions.elementToBeClickable(link_DrivingExperiences)).isEnabled();
try {
if (test == true) {
link_DrivingExperiences.click();
}
System.out.println("Successfully clicked on the driving experience button, using locator: " + "<" + link_DrivingExperiences.toString() + ">");
}catch (TimeoutException e) {
System.out.println("WHY DONT I PRINT ANYTHING??????" + e.getMessage());
}catch (Exception e) {
System.out.println("Unable to click on the Driving Experience Button, Exception: " + e.getMessage());
} finally {
// final code here
}
}
Most likely timeout exception throws out of this.wait.until(ExpectedConditions.elementToBeClickable(link_DrivingExperiences)).isEnabled();, and your try-catch block doesn't enclose that line
Put this.wait.until inside try block.
Exception message already tells that the exception occurred when it was waiting for the element to be clickable.
public void clickDrivingExperienceButton() throws Exception {
try {
boolean test = this.wait.until(ExpectedConditions.elementToBeClickable(link_DrivingExperiences)).isEnabled();
if (test == true) {
link_DrivingExperiences.click();
}
System.out.println("Successfully clicked on the driving experience button, using locator: " + "<" + link_DrivingExperiences.toString() + ">");
}catch (TimeoutException e) {
System.out.println("WHY DONT I PRINT ANYTHING??????" + e.getMessage());
}catch (Exception e) {
System.out.println("Unable to click on the Driving Experience Button, Exception: " + e.getMessage());
} finally {
// final code here
}
}
Your try-catch isn't catching the exception because the exception comes from the 2nd line (wait.until) and that's not inside the try-catch.
You've got many of the same issues that I addressed in your other question, https://stackoverflow.com/a/42120129/2386774, that I would suggest that you fix up in this code also.
It should basically be the below
public void clickDrivingExperienceButton() throws Exception
{
this.wait.until(ExpectedConditions.elementToBeClickable(link_DrivingExperiences)).click();
}
You shouldn't really need to log as much as you are logging. If the element is successfully clicked, the script will progress. Logging that is just going to clog up your logs, IMO. There's also no point in logging an exception because it's going to be dumped to the logs anyway. Generally, you want your script to stop when an exception is thrown unless proceeding won't be affected by it. That largely depends on your scenario so you will have to make the final decision on whether to proceed or not which will determine how you handle thrown exceptions.
I am new to programming and have a noob question. I am trying to run a test like so...
#Test
public void rememberTest()
throws DuplicateException{
try{
personA.remember(sighting4);
}
catch (Exception e) {
fail("Failed" + e.getMessage());
}
try{
assertEquals(personA.remember(sighting3), "The list already contains this sighting");
}
catch (Exception e) {
fail("Failed" + e.getMessage());
}
}
the first try/catch compiles but the second one does not. It tells me "'void' type not allowed here.
" Why can't I use a void? If I can't use a void type, then how would I build my test so that the exception is thrown?
some background info: rememberTest is a test of the remember method that adds an item to an ArrayList.
the remember method, in Class Person, is as follows:
public void remember(final Sighting s)
throws DuplicateException
{
if(lifeList.contains(s)) {
throw new DuplicateException("The list already contains this sighting");
}
lifeList.remember(s);
}
If you need more info please request and I will post it as required.
since you method has already ensured that no duplicate value will be added then I suggest to remove the assertEquals from your code,
#Test
public void rememberTest()
throws DuplicateException{
try{
personA.remember(sighting4);
}
catch (Exception e) {
fail("Failed" + e.getMessage());
}
try{
personA.remember(sighting3), //this will throws Exception if sighting3 is already in.
}
catch (Exception e) {
fail("Failed" + e.getMessage());
}
}
to demonstrate edit your code to this:
#Test
public void rememberTest()
throws DuplicateException{
Sighting s1=//initialize s1
Sighting s2=s1;
try{
personA.remember(s1);
}
catch (Exception e) {
fail("Failed" + e.getMessage());
}
try{
personA.remember(s2), //This will throw an exception because s1 and s2 are pointed to the same object
}
catch (Exception e) {
fail("Failed" + e.getMessage());
}
}
I think instead of doing assert you should use the #Expected annotation which expects for the DuplicateException since its a test case
for the purpose of throwing the exception and catching it in the test Class, do some such thing as this:
try{
personA.remember(sightingSame);
}
catch (DuplicateException e) {
assertEquals("The list already contains this sighting", e.getMessage());
}
catch (Exception e) {
fail("Failed" + e.getMessage());
}
Can we catch an exception type twice in the main method with different messages? I want to print out a different warning.
Ex:
try {
// some code
} catch (NumberFormatException e) {
System.out.println("Wrong input!");
} catch (NumberFormatException e) {
System.out.println("No valid number!");
}
You cannot catch the same exception type (like NumberFormatException) twice. I suggest you catch it once but in the catch block, you print two messages instead.
As i understand your comments you want to display the right message for your exception:
try {
// some code
} catch (NumberFormatException e) {
System.out.println(e.getMessage());
}
You can´t catch the same exception twice.
What you can do is to throw a custom exception in your code and catch it if you want a different behaviour.
try{
...
throw new YourException(yourMessage);
}catch(YourException e){
}
You can´t catch the same exception twice.
Consider the following example,
try {
} catch (FileNotFoundException e) {
System.err.println("FileNotFoundException: " + e.getMessage());
throw new SampleException(e);
} catch (IOException e) {
System.err.println("Caught IOException: " + e.getMessage());
}
Here,
Both handlers print an error message. The second handler does nothing else. By catching any IOException that's not caught by the first handler, it allows the program to continue executing.
The first handler, in addition to printing a message, throws a user-defined exception.