Exception Handling in Selenium WebDriver
By Sourojit Das, Community Contributor - August 21, 2024
What is Exception?
An exception is an incident that disturbs the normal flow of a program’s execution. When an unexpected occurrence occurs during the execution of a program, an exception object is created to reflect the specific error or unexpected state.
An Exception could be caused by a variety of factors, including:
- Logical errors occur when the code does not function as expected or when improper reasoning causes an unexpected circumstance.
- Runtime errors occur during program execution and are commonly caused by improper input, division by zero, or attempting to access an array element that does not exist.
- System Errors occur when the software experiences challenges with system resources, such as running out of memory or experiencing file I/O errors.
To properly handle exceptions, programming languages provide methods such as try-except blocks (try-catch in some languages), in which code that may cause an exception is trapped within a try block and potential exceptions are caught and handled in except blocks. This helps to gracefully manage failures and keep the software stable.
- What is Exception?
- Why is Exception Handling in Selenium Important?
- What happens when you don’t use Exception Handling in Selenium?
- Can you do error handling without Exception Handling in Selenium?
- Common Exceptions in Selenium WebDriver
- Some New Exceptions in Selenium 4.0
- Some Deprecated Selenium Exceptions
- Selenium Resources
Why is Exception Handling in Selenium Important?
Exception handling is significant because it provides critical information about problems encountered during the execution of automated tests or browser interactions.
When utilizing Selenium with BrowserStack, exception handling becomes critical due to the added layer of remote execution and the possibility of network-related errors, in addition to standard Selenium exception handling.
What happens when you don’t use Exception Handling in Selenium?
If you do not use exception handling in Selenium, various negative consequences may arise, compromising the robustness and reliability of your test automation scripts:
1. Uncaught Errors Halt Execution: Errors (e.g., missing elements, timeouts, stale references) cause the script to crash and terminate abruptly. This prevents the remaining test cases from executing, resulting in incomplete test runs and missing defects.
For example, if an element is missing from the page, a NoSuchElementException is issued, and the script terminates without further action.
2. Lack of Error Reporting: Without exception handling, you lose the ability to adequately manage and log errors. This makes debugging difficult because there is no organized means to collect and report faults, resulting in greater time and effort spent diagnosing problems.
For example, if a script fails due to an uncaught exception, the lack of thorough logging may prevent developers from understanding why the failure occurred.
3. Inconsistent Test Results: Tests may react unpredictably if mistakes are not controlled, resulting in inconsistent findings. For example, a test that fails owing to a missing element may pass when the element reappears, suggesting that there was an intermittent problem.
For example, a test that expects an alert to occur may pass without detecting an issue if the alert does not arrive, but the lack of an exception means you miss the fact that anything went wrong.
4. Inability to Handle Dynamic Content: Web pages frequently contain dynamic content, and without exceptions such as StaleElementReferenceException, you cannot effectively manage scenarios in which elements change or update. This can lead to unnecessary test failures.
For example, if the DOM updates after identifying an element, the reference becomes stale (StaleElementReferenceException). Without exception handling, the test fails rather than retrying or relocating the element.
5. Reduced Maintainability: Tests become increasingly difficult to maintain as more hardcoded assumptions are introduced.
For example, presuming that every page load would occur within a certain time limit without accounting for potential timeouts might make scripts brittle. A TimeoutException may arise if a page takes longer to load than expected. Without this, you cannot construct a retry system, resulting in many failures.
Can you do error handling without Exception Handling in Selenium?
While it may not be the best approach, you can handle errors in Selenium without relying directly on exceptions by using alternative techniques and approaches.
Here are some strategies for handling errors in Selenium Python gracefully:
1. Implicit Waits
Implicit waits can help manage situations where elements are not immediately available by setting a default waiting time. This reduces the likelihood of encountering NoSuchElementException when elements are not immediately present.
from selenium import webdriver
driver = webdriver.Chrome() driver.implicitly_wait(10) # Waits up to 10 seconds for elements to appear
2. Explicit Waits
Explicit waits allow you to wait for specific conditions to be met before proceeding. This approach can help avoid exceptions related to timing issues.
from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC driver = webdriver.Chrome() wait = WebDriverWait(driver, 10) element = wait.until(EC.presence_of_element_located((By.ID, 'element_id')))
3. Polling with Retry Logic
Implement polling mechanisms to check for conditions or element availability without using exception handling directly. This involves creating custom retry logic.
import time
from selenium.webdriver.common.by import By def wait_for_element(driver, by, value, timeout=10): end_time = time.time() + timeout while time.time() < end_time: elements = driver.find_elements(by, value) if elements: return elements[0] time.sleep(1) return None element = wait_for_element(driver, By.ID, 'element_id') if element: element.click() else: print("Element not found within the timeout period")
4. Check Element Properties
Before performing actions on elements, check if they are present, visible, and interactable using methods such as is_displayed().
element = driver.find_element(By.ID, 'element_id') if element.is_displayed(): element.click() else: print("Element is not displayed")
5. Use Page Object Model (POM)
Encapsulate interactions and checks in page objects. This can centralize error handling logic and make your tests more maintainable.
class LoginPage: def __init__(self, driver): self.driver = driver self.username_field = (By.ID, 'username') self.password_field = (By.ID, 'password') self.login_button = (By.ID, 'login') def enter_username(self, username): element = self.driver.find_element(*self.username_field) if element.is_displayed(): element.send_keys(username) else: print("Username field is not displayed") def enter_password(self, password): element = self.driver.find_element(*self.password_field) if element.is_displayed(): element.send_keys(password) else: print("Password field is not displayed") def click_login(self): element = self.driver.find_element(*self.login_button) if element.is_displayed(): element.click() else: print("Login button is not displayed")
Common Exceptions in Selenium WebDriver
When using Selenium WebDriver, you may encounter a few common exceptions. These exceptions can occur as a result of errors with element location, browser interaction, or timing.
Note: All the examples of Exceptions are in Selenium Python
Below are some of the most typical exceptions in Selenium WebDriver:
1. MoveTargetOutOfBoundsException
MoveTargetOutOfBounds Exception occurs when attempting to interact with an element that is not within the viewable area of the browser. For instance, when the element is located outside the viewable area, often due to scrolling issues.
element = driver.find_element(By.ID, "element_out_of_view") actions = ActionChains(driver) actions.move_to_element(element).perform() # Raises exception if element is out of bounds
Solution:
To prevent this exception, you can use JavaScript to scroll the element into view before interacting with it. The specific Selenium method where the JavaScript code should be added is ‘execute_script’.
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains # Initialize the Chrome WebDriver driver = webdriver.Chrome() # Navigate to the webpage driver.get("https://example.com") try: # Locate the element that is out of view element = driver.find_element(By.ID, "element_out_of_view") # Scroll the element into view using JavaScript driver.execute_script("arguments[0].scrollIntoView(true);", element) # Now perform the action after ensuring the element is in view actions = ActionChains(driver) actions.move_to_element(element).perform() except MoveTargetOutOfBoundsException as e: print("Element is out of bounds: ", e) finally: # Close the browser session driver.quit()
2. InvalidArgumentException
Thrown when an argument passed to a method is invalid. Occurs when incorrect arguments are provided, such as invalid locators or options.
from selenium import webdriver from selenium.common.exceptions import InvalidArgumentException driver = webdriver.Chrome() try: # Passing an invalid URL format to the driver driver.get("invalid-url") except InvalidArgumentException as e: print("Invalid Argument: ", e) driver.quit()
Solution:
A good way to resolve this is to:
- Validate Input: Ensure that the input provided to WebDriver methods is correct and valid.
- Use Proper URL Formats: Always pass a correctly formatted URL (including http:// or https://).
url = "http://valid-url.com" if url.startswith("http://") or url.startswith("https://"): driver.get(url) else: print("Invalid URL format")
3. UnhandledAlertException
Raised when an unexpected alert is present. Commonly occurs when an alert appears, but the script doesn’t handle it, and further actions fail.
from selenium import webdriver from selenium.common.exceptions import UnhandledAlertException driver = webdriver.Chrome() driver.get("https://example.com") # Assuming an alert is triggered by some action driver.execute_script("alert('This is an alert');") try: # Trying to perform some action without handling the alert driver.find_element_by_id("someElement").click() except UnhandledAlertException as e: print("Unhandled Alert: ", e) # Handling the alert alert = driver.switch_to.alert alert.accept() driver.quit()
Solution:
A good way to resolve this is to:
- Handle Alerts: Always check for and handle alerts before proceeding with any other interactions.
- Use Try-Catch: Encapsulate actions in a try-catch block and handle alerts if they appear.
try: alert = driver.switch_to.alert alert.accept() # or alert.dismiss() if you want to dismiss it except NoAlertPresentException: print("No alert present")
4. JavascriptException
Thrown when executing JavaScript through Selenium fails. Occurs when the script provided in execute_script is incorrect or causes an error in the browser.
from selenium import webdriver from selenium.common.exceptions import JavascriptException driver = webdriver.Chrome() driver.get("https://example.com") try: # Executing incorrect JavaScript driver.execute_script("return document.getElementByID('nonExistentId');") except JavascriptException as e: print("JavaScript Execution Failed: ", e) driver.quit()
Solution:
A good way to resolve this is to:
- Verify JavaScript Code: Ensure that the JavaScript code you are executing is correct and does not contain errors.
- Test JavaScript Independently: Run the JavaScript code independently in the browser console to check for errors before using it in Selenium.
try: result = driver.execute_script("return document.getElementById('validId');") if result is None: print("Element not found") except JavascriptException as e: print("JavaScript Error: ", e)
5. NoAlertPresentException
Raised when an expected alert is not present. Happens when trying to interact with an alert that doesn’t exist.
from selenium import webdriver from selenium.common.exceptions import NoAlertPresentException driver = webdriver.Chrome() driver.get("https://example.com") try: # Attempting to switch to an alert that does not exist alert = driver.switch_to.alert alert.accept() except NoAlertPresentException as e: print("No Alert Present: ", e) driver.quit()
Solution:
A good way to resolve this is to:
- Check for Alerts: Always check if an alert is present before trying to interact with it.
- Use Conditional Logic: Use a try-catch block to safely handle cases where no alert is present.
try: alert = driver.switch_to.alert alert.accept() except NoAlertPresentException: print("No alert to accept")
Some New Exceptions in Selenium 4.0
6. ElementClickInterceptedException
Element Click Intercepted Exception is raised when an element you try to click is not clickable because another element is blocking it.
from selenium import webdriver from selenium.common.exceptions import ElementClickInterceptedException driver = webdriver.Chrome() driver.get("https://example.com") try: driver.find_element_by_id("blockedElement").click() except ElementClickInterceptedException as e: print("Element was blocked by another element: ", e) # Possible resolution: Scroll the element into view or use JavaScript to click element = driver.find_element_by_id("blockedElement") driver.execute_script("arguments[0].click();", element) driver.quit()
Solution:
- Scroll the Element into View: Use JavaScript to scroll the element into view.
- Click Using JavaScript: If the element is still blocked, clicking via JavaScript can bypass the issue.
7. NoSuchCookieException
Raised when trying to interact with a cookie that doesn’t exist.
from selenium import webdriver from selenium.common.exceptions import NoSuchCookieException driver = webdriver.Chrome() driver.get("https://example.com") try: # Attempting to delete a cookie that does not exist driver.delete_cookie("nonExistentCookie") except NoSuchCookieException as e: print("No such cookie: ", e) # Possible resolution: Check if the cookie exists before trying to delete it if driver.get_cookie("nonExistentCookie") is None: print("Cookie does not exist") driver.quit()
Resolution:
- Check Before Deleting: Use get_cookie to check if the cookie exists before trying to delete or manipulate it.
- Handle Gracefully: Implement a fallback or log that the cookie does not exist.
8. InvalidCoordinatesException
Raised when there is an issue with the coordinates provided for actions like mouse movements.
from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains from selenium.common.exceptions import InvalidCoordinatesException driver = webdriver.Chrome() driver.get("https://example.com") try: action = ActionChains(driver) element = driver.find_element_by_id("someElement") action.move_to_element_with_offset(element, 10000, 10000).perform() # Invalid coordinates except InvalidCoordinatesException as e: print("Invalid coordinates provided: ", e) # Possible resolution: Verify the coordinates before performing the action width, height = element.size['width'], element.size['height'] if 0 <= 10000 < width and 0 <= 10000 < height: action.move_to_element_with_offset(element, 10000, 10000).perform() else: print("Coordinates are out of bounds") driver.quit()
Resolution:
- Verify Coordinates: Ensure that the coordinates are within the bounds of the element before attempting to move to that position.
- Use Element Size: Use the element’s size to validate that the coordinates fall within the element’s dimensions.
9. InvalidSessionIdException
Raised when the session ID used in a request is invalid or has expired.
from selenium import webdriver from selenium.common.exceptions import InvalidSessionIdException driver = webdriver.Chrome() driver.get("https://example.com") driver.quit() try: # Attempting to interact after quitting the session driver.find_element_by_id("someElement").click() except InvalidSessionIdException as e: print("Session ID is invalid or expired: ", e) # Possible resolution: Start a new session driver = webdriver.Chrome() driver.get("https://example.com")
Resolution:
- Check Session Status: Ensure that the WebDriver session is still active before making requests.
- Restart Session: If the session is invalid or expired, start a new WebDriver session.
10. ElementNotInteractableException
Element Not Interactable Exception is raised when an element is found but is not interactable (e.g., it’s hidden or disabled).
from selenium import webdriver from selenium.common.exceptions import ElementNotInteractableException from selenium.webdriver.common.by import By import time # Initialize the Chrome WebDriver driver = webdriver.Chrome() try: # Navigate to the webpage driver.get("https://example.com") # Attempt to interact with an element (e.g., a hidden or disabled button) element = driver.find_element(By.ID, "hiddenButton") element.click() except ElementNotInteractableException as e: print("Element is not interactable: ", e) # Resolution: Wait until the element becomes interactable time.sleep(5) # Wait for 5 seconds (or use WebDriverWait for a dynamic wait) element = driver.find_element(By.ID, "hiddenButton") # Try clicking again after waiting if element.is_enabled() and element.is_displayed(): element.click() else: print("Element is still not interactable.") finally: # Close the browser session driver.quit()
Resolution
The primary resolution method for an ElementNotInteractableException is to ensure that the element is both visible and enabled before interacting with it.
This can be achieved using:
- Explicit Wait: Use WebDriverWait to wait until the element becomes interactable.
- Time Delay: Introduce a delay (using time.sleep()) to give the element time to become interactable.
Some Deprecated Selenium Exceptions
Certain exceptions have been removed or deprecated in newer Selenium versions, most notably Selenium 4. These changes are frequently made to simplify the API, eliminate duplication, or enhance the overall developer experience.
Following are some exceptions that may have been abandoned, made redundant, or deprecated:
11. ElementNotVisibleException
Status: Deprecated in Selenium 3 and eliminated in Selenium 4.
Replaced by ElementNotInteractableException. The new exception better captures scenarios in which an element exists in the DOM but cannot be manipulated, such as when it is hidden or disabled.
12. StaleElementReferenceException
Status: While it has not been completely eliminated, its use has decreased as better practices and tools have been implemented to avoid stale element concerns. The deprecation is mainly about transferring the focus to improved handling techniques.
Replacement: Developers are urged to utilize WebDriverWait to avoid scenarios that cause this exception.
13. InvalidSelectorException
Status: Deprecated as better validation and more specific exceptions for selector errors have been introduced.
Replacement: This broad exception is no longer required because more descriptive exceptions or built-in validation exist.
14. InvalidElementStateException
Status: Although it is still available, its utility is decreasing as Selenium adds more precise exceptions for various phases of element interaction.
Replacement: More typical exceptions include ElementClickInterceptedException and ElementNotInteractableException.
15. WebDriverException
Status: This exception has not been completely deleted, but its widespread use is being discouraged in favor of more precise exceptions that provide more information about the exact problem.
Replacement: Use scenario-specific exceptions for example TimeoutException, or NoSuchWindowException).
The removal or deprecation of these exceptions simplifies the error-handling process and encourages developers to build more robust, and specific code. As Selenium evolves, developers are guided to better practices through these modifications.
Selenium Resources
- Selenium Python Tutorial (with Example)
- Page Object Model and Page Factory in Selenium Python
- Understanding ExpectedConditions in Selenium
- Understanding Role of Thread.sleep() in Selenium
- Headless Browser Testing With Selenium Python
- How to install GeckoDriver for Selenium Python?
- How to perform Web Scraping using Selenium and Python
- How to Create and Use Action Class in Selenium Python
- How to download a file using Selenium and Python
- How to Press Enter without Element in Selenium Python?
- UI Automation using Python and Selenium: Tutorial
- Get Current URL in Selenium using Python: Tutorial
Conclusion
Exception handling is a very crucial part of every Selenium Script. Exceptions in Selenium can not be ignored as they disrupt the normal execution of programs. One can write optimal and robust scripts by handling the Exceptions in unique ways. Programmers can handle standard exceptions using various techniques like Try/catch, Multiple catch blocks, Finally, and others depending upon the requirement of scripts.