Understanding Implicit vs Explicit Waits in Selenium with Python

πŸ’‘ Problem Formulation: In web automation using Selenium with Python, it’s crucial to manage the timing on how you locate and interact with web elements. This often involves waiting for elements to load or become clickable. The two primary ways to handle these waits are through implicit and explicit waits. For instance, when navigating to a dynamic page, we may need a reliable method to wait for elements to become available before interacting with them.

Method 1: Implicit Waits

Implicit Waits are used in Selenium to tell the WebDriver to poll the DOM for a certain amount of time when trying to find an element or elements if they are not immediately available. The default setting is 0 seconds, meaning the WebDriver will NOT wait before throwing a “NoSuchElementException” if the element is not found. This setting is set for the entire lifecycle of the WebDriver object.

Here’s an example:

from selenium import webdriver

driver = webdriver.Chrome()
driver.implicitly_wait(10) # seconds
driver.get("http://example.com")
my_element = driver.find_element_by_id('my_element_id')

The WebDriver will wait up to 10 seconds before throwing an exception if the element is not found.

In the example above, the implicitly_wait method sets a sticky timeout of 10 seconds where the WebDriver will continually check for the presence of the element before giving up. It simplifies the code since you don’t need to repeatedly specify wait conditions for each element. However, the downside is that it could potentially slow down test execution because it applies to all element searches.

Method 2: Explicit Waits

Explicit Waits in Selenium are used to halt the program execution until a certain condition is met or the maximum timeout is reached. They are configured with the WebDriverWait and expected_conditions classes provided by the Selenium package. Explicit waits are more flexible than implicit waits because they allow you to wait for specific conditions on an element, such as visibility, clickability, or the presence of a particular text.

Here’s an example:

from selenium import webdriver
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()
driver.get("http://example.com")

wait = WebDriverWait(driver, 10)
my_element = wait.until(EC.presence_of_element_located((By.ID, 'my_element_id')))

The program will wait up to 10 seconds for the element to be present before throwing a “TimeoutException”.

As shown above, explicit waits are specified per element search with WebDriverWait combined with expected_conditions, which makes them more precise for each case. They provide better handling for non-linear web page transition times but require more boilerplate code and increase the complexity of your tests.

Method 3: Custom Wait Conditions

Sometimes the predefined expected conditions are not sufficient for the requirements of your test, in which case custom wait conditions can be used. This involves writing a function that Selenium will call repeatedly until it returns True or the timeout is reached.

Here’s an example:

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait

driver = webdriver.Chrome()
driver.get("http://example.com")

def element_has_css_class(driver):
    element = driver.find_element_by_id("my_element_id")
    return "my-class" in element.get_attribute('class')

wait = WebDriverWait(driver, 10)
my_element = wait.until(element_has_css_class)

The driver will wait up to 10 seconds for the element to have the “my-class” CSS class applied before timing out.

The custom wait condition checks for a specific CSS class in the element by using a custom function that gets the element’s class attribute and searches for “my-class” within it. Custom conditions provide the freedom to wait for more complex scenarios, offering a powerful tool for robust test development.

Method 4: Combining Implicit and Explicit Waits

It’s generally advised not to mix implicit and explicit waits because it can lead to unpredictable wait times. However, for those who are curious about the behavior, caution and thorough knowledge are required when combining them.

Here’s an example:

Due to the unpredictable and potentially unstable nature, a code example is not provided to dissuade the use of mixing methods.

Unpredictable and longer wait times may result when combining the two, leading to increased complexity and potentially flaky tests.

Bonus One-Liner Method 5: Zero Wait Time

If you have a test case with elements that should be present immediately, you can set zero wait times to ensure that your test fails fast if the expected condition is not met.

Here’s an example:

from selenium import webdriver

driver = webdriver.Chrome()
driver.implicitly_wait(0) # Set to zero wait time
# Remainder of the test steps that expect immediate element visibility

The WebDriver will not wait at all and will immediately throw an exception if the element is not found.

This straightforward approach is best when you expect all elements to be present immediately after a page load, and it can help in quickly identifying when elements are not loading as fast as expected.

Summary/Discussion

  • Method 1: Implicit Waits. Straightforward configuration. Applies globally, which can slow down tests. Not recommended for conditions with complex timing.
  • Method 2: Explicit Waits. Flexible and allows for case-specific conditions. Can be more complicated to setup. Preferred for dynamic content and AJAX applications.
  • Method 3: Custom Wait Conditions. Powerful for complex situations. Requires custom code and more understanding of the WebDriver and expected conditions.
  • Method 4: Combining Implicit and Explicit Waits. Generally not recommended. Can create unreliable and hard-to-debug test code.
  • Bonus One-Liner Method 5: Zero Wait Time. Can be useful for ‘fail-fast’ scenarios, mainly during debugging. Not suitable for applications with any load time whatsoever.