Popular Searches
Popular Course Categories
Popular Courses

Waits with Python

Selenium with Python

Waits with Python in Selenium

Waits are one of the most important concepts in Selenium automation because modern web applications frequently load elements dynamically. An element may exist in the DOM but may not yet be visible, enabled, clickable, or ready for interaction when Selenium attempts to use it.

Selenium waits allow a Python automation script to synchronize browser actions with the actual state of the web application. Instead of assuming that an element will be immediately available, the script can wait until a required condition is satisfied.

In professional Selenium automation, waits help reduce timing-related failures, improve test stability, and make scripts more reliable when working with dynamic pages, AJAX requests, animations, delayed elements, frames, alerts, windows, and asynchronous application behavior.

Course Resource: Selenium Training | Register for Course Demo


1. What are Waits in Selenium?

A Selenium wait is a synchronization mechanism that instructs WebDriver to pause execution until a specified condition is satisfied or a timeout is reached.

Without proper synchronization, Selenium may attempt to interact with an element before the browser has finished rendering or updating the page.

Basic Example

from selenium.webdriver.support.ui import WebDriverWait

 

wait = WebDriverWait(driver, 10)

The above statement creates a wait that can wait for a condition for up to 10 seconds.

2. Why are Waits Important?

Web applications are rarely completely static. Pages can contain JavaScript, AJAX requests, animations, lazy-loaded components, asynchronous API calls, dynamic tables, popups, and elements that appear after user interaction.

  • Synchronize automation with the application.
  • Reduce timing-related failures.
  • Handle dynamically loaded elements.
  • Improve test stability.
  • Reduce unnecessary fixed delays.
  • Handle asynchronous browser operations.
  • Wait for elements to become interactable.
  • Improve reliability of regression tests.
  • Make automation more maintainable.

3. Selenium Script Without Proper Wait

Consider a page where a login button appears two seconds after the page loads.

driver.get("https://example.com/login")

 

driver.find_element(

    By.ID,

    "login"

).click()

If the button is not ready when Selenium searches for it, the script can fail with an exception such as NoSuchElementException or another interaction-related exception.

4. Selenium Script with a Wait

from selenium.webdriver.common.by import By

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.support import expected_conditions as EC

 

login_button = WebDriverWait(

    driver,

    10

).until(

    EC.element_to_be_clickable(

        (By.ID, "login")

    )

)

 

login_button.click()

This approach waits for the required condition instead of assuming that the button is immediately ready.

5. Types of Waits in Selenium

Selenium automation commonly uses three synchronization approaches:

Wait TypeDescriptionTypical Usage
Implicit WaitSets a default timeout for element location operations.Simple global synchronization.
Explicit WaitWaits for a specific condition.Dynamic elements and application states.
Fluent WaitProvides configurable timeout, polling, and ignored exceptions.Advanced synchronization requirements.

6. Implicit Wait

An implicit wait tells WebDriver to wait for a specified amount of time when attempting to locate an element before returning an error.

driver.implicitly_wait(10)

After this configuration, Selenium uses the specified timeout for element-location operations.

Example

from selenium import webdriver

from selenium.webdriver.common.by import By

 

driver = webdriver.Chrome()

 

driver.implicitly_wait(10)

 

driver.get("https://example.com")

 

username = driver.find_element(

    By.ID,

    "username"

)

 

username.send_keys("admin")

7. How Implicit Wait Works

Find Element

     |

     v

Element Available?

   /       \

 Yes        No

 |           |

 v           v

Return      Wait

Element       |

               v

        Search Again

               |

               v

        Timeout Reached?

          /        \

        No          Yes

        |            |

        v            v

      Retry       Exception

8. Setting an Implicit Wait

driver.implicitly_wait(10)

The value is specified in seconds.

driver.implicitly_wait(5)

This configures a five-second implicit wait.

9. Advantages of Implicit Wait

  • Simple to configure.
  • Applies globally to element location.
  • Reduces immediate failures when elements take time to appear.
  • Requires less repeated code.

10. Limitations of Implicit Wait

  • It does not express a specific application condition.
  • It is less precise than explicit waits.
  • It is not intended for conditions such as waiting for a particular text value.
  • Mixing implicit and explicit waits can make timing behavior harder to reason about.
  • It may hide synchronization problems when used as the only waiting strategy.

11. Explicit Wait

An explicit wait waits for a specific condition before allowing the script to continue.

Python Selenium provides WebDriverWait for explicit waits, and Selenium's expected conditions module provides commonly used conditions.

Basic Syntax

WebDriverWait(

    driver,

    timeout

).until(

    condition

)

12. Basic Explicit Wait Example

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.support import expected_conditions as EC

 

element = WebDriverWait(

    driver,

    10

).until(

    EC.visibility_of_element_located(

        (By.ID, "username")

    )

)

The script waits up to 10 seconds for the username element to become visible.

13. Explicit Wait Flow

Start Wait

    |

    v

Check Condition

    |

    v

Condition Satisfied?

   /          \

 Yes           No

 |              |

 v              v

Continue     Poll Again

                 |

                 v

          Timeout Reached?

             /       \

           No         Yes

           |           |

           v           v

        Retry      TimeoutException

14. WebDriverWait

WebDriverWait is used to wait for a condition until the timeout is reached.

wait = WebDriverWait(driver, 10)

 

element = wait.until(

    EC.visibility_of_element_located(

        (By.ID, "username")

    )

)

15. Reusing WebDriverWait

Instead of creating a new wait object repeatedly, a reusable wait object can be created.

wait = WebDriverWait(driver, 10)

 

username = wait.until(

    EC.visibility_of_element_located(

        (By.ID, "username")

    )

)

 

password = wait.until(

    EC.visibility_of_element_located(

        (By.ID, "password")

    )

 

login_button = wait.until(

    EC.element_to_be_clickable(

        (By.ID, "login")

    )

)

16. Expected Conditions

Expected Conditions provide predefined conditions that can be used with explicit waits.

ConditionPurpose
presence_of_element_located()Waits until an element is present in the DOM.
visibility_of_element_located()Waits until an element is present and visible.
element_to_be_clickable()Waits until an element is visible and enabled for clicking.
presence_of_all_elements_located()Waits until matching elements are present.
visibility_of_all_elements_located()Waits until matching elements are visible.
invisibility_of_element_located()Waits until an element becomes invisible or is no longer present.
text_to_be_present_in_element()Waits for specific text in an element.
title_contains()Waits until the page title contains specified text.
title_is()Waits until the page title matches expected text.
url_contains()Waits until the URL contains specified text.
alert_is_present()Waits for an alert to appear.
frame_to_be_available_and_switch_to_it()Waits for a frame and switches into it.
number_of_windows_to_be()Waits until the required number of windows exists.

17. Presence of Element

presence_of_element_located() waits until an element exists in the DOM. Presence does not necessarily mean that the element is visible or ready for user interaction.

element = WebDriverWait(

    driver,

    10

).until(

    EC.presence_of_element_located(

        (By.ID, "username")

    )

)

18. Visibility of Element

visibility_of_element_located() waits until the element is present and visible.

username = WebDriverWait(

    driver,

    10

).until(

    EC.visibility_of_element_located(

        (By.ID, "username")

    )

)

 

username.send_keys("admin")

19. Presence vs Visibility

PresenceVisibility
Element exists in DOM.Element exists and is visible.
Element may not be displayed.Element can be displayed.
Useful for DOM-level presence.Useful before visual interaction.

20. Element to be Clickable

element_to_be_clickable() is useful when the script needs to click an element after it becomes visible and enabled.

button = WebDriverWait(

    driver,

    10

).until(

    EC.element_to_be_clickable(

        (By.ID, "submit")

    )

)

 

button.click()

21. Waiting for Multiple Elements

When a page contains a collection of elements, use presence_of_all_elements_located().

products = WebDriverWait(

    driver,

    10

).until(

    EC.presence_of_all_elements_located(

        (By.CSS_SELECTOR, ".product")

    )

)

 

print("Products:", len(products))

22. Waiting for All Elements to be Visible

products = WebDriverWait(

    driver,

    10

).until(

    EC.visibility_of_all_elements_located(

        (By.CSS_SELECTOR, ".product")

    )

)

23. Waiting for Invisibility

Sometimes the script must wait for a loading spinner, popup, overlay, or progress indicator to disappear.

WebDriverWait(

    driver,

    10

).until(

    EC.invisibility_of_element_located(

        (By.ID, "loading")

    )

)

24. Waiting for Text

Dynamic applications may initially display one message and later update it. Explicit waits can be used to wait for specific text.

WebDriverWait(

    driver,

    10

).until(

    EC.text_to_be_present_in_element(

        (By.ID, "status"),

        "Completed"

    )

)

25. Waiting for Page Title

WebDriverWait(

    driver,

    10

).until(

    EC.title_is("Dashboard")

)

To wait until the title contains specific text:

WebDriverWait(

    driver,

    10

).until(

    EC.title_contains("Dashboard")

)

26. Waiting for URL

URL-based waits are useful after navigation or login.

WebDriverWait(

    driver,

    10

).until(

    EC.url_contains("/dashboard")

)

27. Waiting for an Alert

When a JavaScript alert appears asynchronously, an explicit wait can be used.

alert = WebDriverWait(

    driver,

    10

).until(

    EC.alert_is_present()

)

 

alert.accept()

28. Waiting for a Frame

When an iframe is loaded dynamically, Selenium can wait until the frame becomes available and switch into it.

WebDriverWait(

    driver,

    10

).until(

    EC.frame_to_be_available_and_switch_to_it(

        (By.ID, "payment-frame")

    )

)

29. Waiting for Multiple Windows

When clicking a link opens a new window or tab, the script can wait until the expected number of window handles exists.

original_window = driver.current_window_handle

 

driver.find_element(

    By.ID,

    "open-window"

).click()

 

WebDriverWait(

    driver,

    10

).until(

    EC.number_of_windows_to_be(2)

)

30. Custom Conditions with lambda

Explicit waits can also use custom Python conditions through a lambda expression.

WebDriverWait(

    driver,

    10

).until(

    lambda d: d.find_element(

        By.ID,

        "status"

    ).text == "Completed"

)

31. Waiting for an Attribute

Dynamic web applications may update attributes such as class, value, disabled, or custom data attributes.

WebDriverWait(

    driver,

    10

).until(

    lambda d: d.find_element(

        By.ID,

        "status"

    ).get_attribute("data-state") == "ready"

)

32. Waiting for an Element's Value

WebDriverWait(

    driver,

    10

).until(

    lambda d: d.find_element(

        By.ID,

        "search"

    ).get_attribute("value") == "Selenium"

)

33. Waiting for a Button to Become Enabled

submit = WebDriverWait(

    driver,

    10

).until(

    lambda d: (

        element := d.find_element(

            By.ID,

            "submit"

        )

    ).is_enabled() and element

)

 

submit.click()

34. Waiting for a Loader to Disappear

WebDriverWait(

    driver,

    15

).until(

    EC.invisibility_of_element_located(

        (By.CSS_SELECTOR, ".loader")

    )

)

 

dashboard = WebDriverWait(

    driver,

    10

).until(

    EC.visibility_of_element_located(

        (By.ID, "dashboard")

    )

)

35. Waiting for AJAX Content

AJAX-based pages can update content without performing a complete page refresh. The automation script should wait for the application state that indicates the AJAX operation has completed.

WebDriverWait(

    driver,

    15

).until(

    EC.visibility_of_element_located(

        (By.ID, "results")

    )

)

36. Waiting for Dynamic Search Results

search_box = WebDriverWait(

    driver,

    10

).until(

    EC.visibility_of_element_located(

        (By.ID, "search")

    )

)

 

search_box.send_keys("Laptop")

 

results = WebDriverWait(

    driver,

    10

).until(

    EC.presence_of_all_elements_located(

        (By.CSS_SELECTOR, ".search-result")

    )

)

 

print("Results:", len(results))

37. Waiting for a Dynamic Login

username = WebDriverWait(

    driver,

    10

).until(

    EC.visibility_of_element_located(

        (By.ID, "username")

    )

)

 

password = WebDriverWait(

    driver,

    10

).until(

    EC.visibility_of_element_located(

        (By.ID, "password")

    )

)

 

login_button = WebDriverWait(

    driver,

    10

).until(

    EC.element_to_be_clickable(

        (By.ID, "login")

    )

)

 

username.send_keys("admin")

password.send_keys("admin123")

login_button.click()

 

WebDriverWait(

    driver,

    10

).until(

    EC.url_contains("/dashboard")

)

38. Waiting for a Checkbox

checkbox = WebDriverWait(

    driver,

    10

).until(

    EC.element_to_be_clickable(

        (By.ID, "terms")

    )

)

 

if not checkbox.is_selected():

    checkbox.click()

39. Waiting for a Dropdown

country = WebDriverWait(

    driver,

    10

).until(

    EC.visibility_of_element_located(

        (By.ID, "country")

    )

)

 

from selenium.webdriver.support.ui import Select

 

Select(country).select_by_visible_text("India")

40. Waiting for a Link

documentation = WebDriverWait(

    driver,

    10

).until(

    EC.element_to_be_clickable(

        (By.LINK_TEXT, "Documentation")

    )

)

 

documentation.click()

41. Waiting for a Modal

Modal dialogs may appear after a button click. Instead of using a fixed delay, wait for the modal to become visible.

driver.find_element(

    By.ID,

    "open-modal"

).click()

 

modal = WebDriverWait(

    driver,

    10

).until(

    EC.visibility_of_element_located(

        (By.ID, "modal")

    )

)

 

print(modal.text)

42. Waiting for a Loading Spinner

WebDriverWait(

    driver,

    15

).until(

    EC.invisibility_of_element_located(

        (By.CSS_SELECTOR, ".loading-spinner")

    )

)

43. Waiting for Page Navigation

After clicking a navigation link, the script can wait for a URL change or a specific element on the destination page.

old_url = driver.current_url

 

driver.find_element(

    By.ID,

    "profile"

).click()

 

WebDriverWait(

    driver,

    10

).until(

    lambda d: d.current_url != old_url

)

44. Waiting for Stale Elements

Dynamic pages may replace DOM elements after an update. Selenium provides conditions that can be used when working with stale elements.

element = driver.find_element(

    By.ID,

    "status"

)

 

driver.find_element(

    By.ID,

    "refresh"

).click()

 

WebDriverWait(

    driver,

    10

).until(

    EC.staleness_of(element)

)

45. Handling TimeoutException

If an explicit wait cannot satisfy its condition before the timeout, Selenium raises TimeoutException.

from selenium.common.exceptions import TimeoutException

 

try:

    login_button = WebDriverWait(

        driver,

        10

    ).until(

        EC.element_to_be_clickable(

            (By.ID, "login")

        )

    )

 

    login_button.click()

 

except TimeoutException:

    print("Login button was not ready within the timeout")

46. Waits and Exception Handling

Waits and exception handling have different purposes. A wait synchronizes the script with the application, while exception handling determines how the script responds when an operation fails.

ConceptPurpose
WaitSynchronize with application state.
Exception handlingHandle unexpected execution failures.
AssertionValidate expected test results.

47. Fluent Wait Concept

Fluent wait is an advanced waiting approach where timeout, polling frequency, and ignored exceptions can be configured.

In Python, WebDriverWait can be configured with timeout, polling frequency, and ignored exceptions when required.

Example

from selenium.webdriver.support.ui import WebDriverWait

from selenium.common.exceptions import NoSuchElementException

 

wait = WebDriverWait(

    driver,

    20,

    poll_frequency=1,

    ignored_exceptions=[NoSuchElementException]

)

 

element = wait.until(

    EC.visibility_of_element_located(

        (By.ID, "username")

    )

)

48. Polling Frequency

Polling frequency determines how often the wait checks the condition.

wait = WebDriverWait(

    driver,

    20,

    poll_frequency=1

)

In this example, the condition is checked approximately once per second until it succeeds or the timeout is reached.

49. Ignoring Specific Exceptions During a Wait

In advanced scenarios, a wait may be configured to ignore selected exceptions while repeatedly checking a condition.

from selenium.common.exceptions import NoSuchElementException

 

wait = WebDriverWait(

    driver,

    10,

    ignored_exceptions=[

        NoSuchElementException

    ]

)

Exception ignoring should be used carefully. Ignoring too many exceptions can hide genuine automation problems.

50. Implicit Wait vs Explicit Wait

FeatureImplicit WaitExplicit Wait
ScopeGlobal element location behavior.Specific operation or condition.
ConditionElement location.Custom or predefined condition.
PrecisionLower.Higher.
Dynamic UI HandlingLimited.Strong.
ReadabilitySimple.Very expressive.
Typical UsageBasic synchronization.Professional automation.

51. Explicit Wait vs sleep()

sleep()Explicit Wait
Waits for a fixed amount of time.Waits for a condition.
Does not know whether the application is ready.Checks application state.
Can waste execution time.Continues as soon as condition succeeds.
Less flexible.More flexible.
Useful for specific non-Selenium timing needs.Preferred for Selenium synchronization.

52. Why Avoid Excessive time.sleep()?

time.sleep(10)

 

driver.find_element(

    By.ID,

    "submit"

).click()

If the element becomes ready after two seconds, the script still waits for the complete ten seconds. If the element takes longer than ten seconds, the script may still fail.

A condition-based wait can stop as soon as the required condition becomes true.

53. Better Alternative to sleep()

submit = WebDriverWait(

    driver,

    10

).until(

    EC.element_to_be_clickable(

        (By.ID, "submit")

    )

)

 

submit.click()

54. Do Not Mix Wait Strategies Unnecessarily

Using implicit and explicit waits together can make timeout behavior harder to understand. A project should establish a consistent synchronization strategy and use waits according to the needs of the application.

55. Waits Inside Page Object Model

Wait logic can be placed inside Page Object classes so that test cases remain focused on business behavior.

from selenium.webdriver.common.by import By

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.support import expected_conditions as EC

 

class LoginPage:

    USERNAME = (By.ID, "username")

    PASSWORD = (By.ID, "password")

    LOGIN_BUTTON = (By.ID, "login")

 

    def __init__(self, driver):

        self.driver = driver

        self.wait = WebDriverWait(

            driver,

            10

        )

 

    def login(self, username, password):

        self.wait.until(

            EC.visibility_of_element_located(

                self.USERNAME

            )

        ).send_keys(username)

 

        self.wait.until(

            EC.visibility_of_element_located(

                self.PASSWORD

            )

        ).send_keys(password)

 

        self.wait.until(

            EC.element_to_be_clickable(

                self.LOGIN_BUTTON

            )

        ).click()

56. Reusable Wait Helper

A reusable utility class can centralize common waiting operations.

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.support import expected_conditions as EC

 

class WaitHelper:

    def __init__(self, driver, timeout=10):

        self.driver = driver

        self.wait = WebDriverWait(

            driver,

            timeout

        )

 

    def visible(self, locator):

        return self.wait.until(

            EC.visibility_of_element_located(

                locator

            )

        )

 

    def clickable(self, locator):

        return self.wait.until(

            EC.element_to_be_clickable(

                locator

            )

        )

 

    def present(self, locator):

        return self.wait.until(

            EC.presence_of_element_located(

                locator

            )

        )

57. Using a Wait Helper

wait = WaitHelper(driver)

 

username = wait.visible(

    (By.ID, "username")

)

 

username.send_keys("admin")

 

login = wait.clickable(

    (By.ID, "login")

)

 

login.click()

58. Waiting for API-Driven UI Updates

Many modern applications use APIs to load or update information after the initial page load. Selenium should normally wait for a user-visible application state that confirms the operation is ready.

driver.find_element(

    By.ID,

    "load-data"

).click()

 

WebDriverWait(

    driver,

    15

).until(

    EC.visibility_of_element_located(

        (By.ID, "data-table")

    )

)

59. Waiting for a Table to Load

rows = WebDriverWait(

    driver,

    15

).until(

    EC.presence_of_all_elements_located(

        (By.CSS_SELECTOR, "#users tbody tr")

    )

)

 

print("Rows:", len(rows))

60. Waiting for Search Result Text

WebDriverWait(

    driver,

    10

).until(

    EC.text_to_be_present_in_element(

        (By.ID, "result-message"),

        "Results found"

    )

)

61. Waiting for an Element to Become Enabled

submit = WebDriverWait(

    driver,

    10

).until(

    lambda d: (

        element := d.find_element(

            By.ID,

            "submit"

        )

    ) if element.is_enabled() else False

)

For simpler cases, element_to_be_clickable() is often more readable when the required behavior is simply to wait until an element is visible and enabled for clicking.

62. Waiting for a Checkbox to be Selected

WebDriverWait(

    driver,

    10

).until(

    EC.element_to_be_selected(

        (By.ID, "terms")

    )

)

63. Waiting for a Specific URL

WebDriverWait(

    driver,

    10

).until(

    EC.url_to_be(

        "https://example.com/dashboard"

    )

)

64. Waiting for a Partial URL

WebDriverWait(

    driver,

    10

).until(

    EC.url_contains("/dashboard")

)

65. Waiting for a New Window

original_window = driver.current_window_handle

 

driver.find_element(

    By.ID,

    "open-report"

).click()

 

WebDriverWait(

    driver,

    10

).until(

    EC.number_of_windows_to_be(2)

)

 

for handle in driver.window_handles:

    if handle != original_window:

        driver.switch_to.window(handle)

        break

66. Waiting for a Frame

WebDriverWait(

    driver,

    10

).until(

    EC.frame_to_be_available_and_switch_to_it(

        (By.ID, "payment-frame")

    )

)

 

card_number = WebDriverWait(

    driver,

    10

).until(

    EC.visibility_of_element_located(

        (By.ID, "card-number")

    )

)

 

card_number.send_keys(

    "4111111111111111"

)

 

driver.switch_to.default_content()

67. Waiting for an Alert

driver.find_element(

    By.ID,

    "delete"

).click()

 

alert = WebDriverWait(

    driver,

    10

).until(

    EC.alert_is_present()

)

 

print(alert.text)

alert.accept()

68. Waiting for Dynamic Buttons

button = WebDriverWait(

    driver,

    15

).until(

    EC.element_to_be_clickable(

        (By.CSS_SELECTOR, "button.submit")

    )

)

 

button.click()

69. Waiting for a Message to Disappear

WebDriverWait(

    driver,

    10

).until(

    EC.invisibility_of_element_located(

        (By.ID, "processing-message")

    )

)

70. Waiting for an Element to Become Stale

old_element = driver.find_element(

    By.ID,

    "results"

)

 

driver.find_element(

    By.ID,

    "refresh"

).click()

 

WebDriverWait(

    driver,

    10

).until(

    EC.staleness_of(old_element)

)

71. Handling TimeoutException with Screenshot

from selenium.common.exceptions import TimeoutException

 

try:

    WebDriverWait(

        driver,

        10

    ).until(

        EC.visibility_of_element_located(

            (By.ID, "dashboard")

        )

    )

 

except TimeoutException:

    driver.save_screenshot(

        "timeout_failure.png"

    )

    raise

72. Logging Wait Failures

import logging

from selenium.common.exceptions import TimeoutException

 

try:

    WebDriverWait(

        driver,

        10

    ).until(

        EC.element_to_be_clickable(

            (By.ID, "submit")

        )

    )

 

except TimeoutException as e:

    logging.error(

        "Submit button was not clickable: %s",

        e

    )

    raise

73. Wait Strategy for Login

Open Login Page

      |

      v

Wait for Username

      |

      v

Enter Username

      |

      v

Wait for Password

      |

      v

Enter Password

      |

      v

Wait for Login Button

      |

      v

Click Login

      |

      v

Wait for Dashboard

      |

      v

Validate Dashboard

74. Wait Strategy for E-Commerce

Open Store

    |

    v

Wait for Search Box

    |

    v

Search Product

    |

    v

Wait for Search Results

    |

    v

Select Product

    |

    v

Wait for Product Page

    |

    v

Wait for Add to Cart

    |

    v

Add Product

    |

    v

Wait for Cart

    |

    v

Validate Cart

75. Wait Strategy for Dynamic Forms

Open Form

   |

   v

Wait for Name Field

   |

   v

Enter Name

   |

   v

Wait for Email Field

   |

   v

Enter Email

   |

   v

Wait for Country Dropdown

   |

   v

Select Country

   |

   v

Wait for Submit

   |

   v

Click Submit

   |

   v

Wait for Success Message

76. Common Mistakes with Selenium Waits

Mistake 1: Using sleep() Everywhere

time.sleep(10)

Fixed delays do not adapt to actual application state.

Mistake 2: Using Too Short a Timeout

WebDriverWait(

    driver,

    1

).until(...)

A timeout should be based on realistic application behavior and environment conditions.

Mistake 3: Using Very Large Timeouts Everywhere

WebDriverWait(

    driver,

    300

).until(...)

Very large timeouts can make failures take unnecessarily long to surface.

Mistake 4: Waiting for the Wrong Condition

For example, waiting only for presence when the actual requirement is that the element must be visible and clickable.

Mistake 5: Mixing Implicit and Explicit Waits Without a Strategy

This can make execution timing harder to predict and debug.

Mistake 6: Using Fixed Delays After Every Action

click()

time.sleep(5)

 

send_keys()

time.sleep(5)

Use condition-based synchronization where possible.

Mistake 7: Ignoring TimeoutException

try:

    WebDriverWait(driver, 10).until(...)

except TimeoutException:

    pass

Silently ignoring timeout failures can hide real application or automation problems.


77. Best Practices for Selenium Waits

  • Prefer explicit waits for dynamic application conditions.
  • Use meaningful expected conditions.
  • Choose timeouts based on realistic application behavior.
  • Avoid unnecessary time.sleep() calls.
  • Keep wait logic reusable.
  • Use Page Object Model for large projects.
  • Wait for the state required by the next action.
  • Use element_to_be_clickable() before important clicks when appropriate.
  • Use visibility conditions before visual interactions.
  • Use presence conditions when DOM presence is sufficient.
  • Wait for loaders and overlays to disappear when they block interaction.
  • Handle TimeoutException appropriately.
  • Capture screenshots when wait failures are important for debugging.
  • Log important synchronization failures.
  • Avoid blindly increasing timeout values to hide synchronization problems.
  • Keep the synchronization strategy consistent throughout the project.

78. Good Wait Strategy vs Poor Wait Strategy

Poor StrategyBetter Strategy
Use sleep() everywhereUse condition-based explicit waits
Wait 30 seconds for every actionUse appropriate condition-specific timeouts
Wait for presence before every clickUse clickable condition when clicking
Ignore TimeoutExceptionLog, diagnose, and handle appropriately
Mix waits randomlyUse a consistent synchronization strategy
Repeat wait code everywhereCreate reusable wait utilities
Wait for arbitrary timeWait for application state

79. Practical Project: Dynamic Login Automation

Create a Selenium Python login test for a page where the login form loads dynamically.

Requirements

  1. Open the login page.
  2. Wait for the username field.
  3. Enter the username.
  4. Wait for the password field.
  5. Enter the password.
  6. Wait for the login button to become clickable.
  7. Click the login button.
  8. Wait for the dashboard URL.
  9. Validate the dashboard.
  10. Capture a screenshot if a timeout occurs.
  11. Close the browser.

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

from selenium.common.exceptions import TimeoutException

 

driver = webdriver.Chrome()

 

try:

    driver.get(

        "https://example.com/login"

    )

 

    wait = WebDriverWait(driver, 10)

 

    username = wait.until(

        EC.visibility_of_element_located(

            (By.ID, "username")

        )

    )

 

    password = wait.until(

        EC.visibility_of_element_located(

            (By.ID, "password")

        )

    )

 

    login_button = wait.until(

        EC.element_to_be_clickable(

            (By.ID, "login")

        )

    )

 

    username.send_keys("admin")

    password.send_keys("admin123")

    login_button.click()

 

    wait.until(

        EC.url_contains("/dashboard")

    )

 

    assert "/dashboard" in driver.current_url

 

except TimeoutException:

    driver.save_screenshot(

        "login_timeout.png"

    )

    raise

 

finally:

    driver.quit()

80. Practical Project: Dynamic Search Test

from selenium import webdriver

from selenium.webdriver.common.by import By

from selenium.webdriver.common.keys import Keys

from selenium.webdriver.support.ui import WebDriverWait

from selenium.webdriver.support import expected_conditions as EC

 

driver = webdriver.Chrome()

 

try:

    driver.get(

        "https://example.com/search"

    )

 

    wait = WebDriverWait(driver, 10)

 

    search = wait.until(

        EC.visibility_of_element_located(

            (By.ID, "search")

        )

    )

 

    search.send_keys("Laptop")

    search.send_keys(Keys.ENTER)

 

    results = wait.until(

        EC.presence_of_all_elements_located(

            (By.CSS_SELECTOR, ".result")

        )

    )

 

    assert len(results) > 0

 

finally:

    driver.quit()

81. Practical Project: Dynamic E-Commerce Cart

Build an e-commerce automation test that waits for each application state before continuing.

Open Store

    |

    v

Wait for Search

    |

    v

Search Product

    |

    v

Wait for Results

    |

    v

Select Product

    |

    v

Wait for Product Page

    |

    v

Wait for Add to Cart

    |

    v

Add to Cart

    |

    v

Wait for Cart

    |

    v

Validate Product

    |

    v

Validate Price

    |

    v

Checkout

82. Practical Project: Loader Handling

Many applications display a loading spinner while data is being retrieved. The automation should wait for the spinner to disappear before interacting with the resulting content.

driver.find_element(

    By.ID,

    "load-data"

).click()

 

WebDriverWait(

    driver,

    15

).until(

    EC.invisibility_of_element_located(

        (By.ID, "loader")

    )

)

 

table = WebDriverWait(

    driver,

    10

).until(

    EC.visibility_of_element_located(

        (By.ID, "data-table")

    )

)

83. Practical Project: Frame Wait

WebDriverWait(

    driver,

    15

).until(

    EC.frame_to_be_available_and_switch_to_it(

        (By.ID, "payment-frame")

    )

)

 

card = WebDriverWait(

    driver,

    10

).until(

    EC.visibility_of_element_located(

        (By.ID, "card-number")

    )

)

 

card.send_keys(

    "4111111111111111"

)

 

driver.switch_to.default_content()

84. Practical Project: Alert Wait

driver.find_element(

    By.ID,

    "delete-account"

).click()

 

alert = WebDriverWait(

    driver,

    10

).until(

    EC.alert_is_present()

)

 

print(alert.text)

alert.accept()

85. Practical Project: New Window Wait

original_window = driver.current_window_handle

 

driver.find_element(

    By.ID,

    "open-report"

).click()

 

WebDriverWait(

    driver,

    10

).until(

    EC.number_of_windows_to_be(2)

)

 

for handle in driver.window_handles:

    if handle != original_window:

        driver.switch_to.window(handle)

        break

 

print(driver.title)


86. Waits in a Professional Selenium Framework

In a professional automation framework, synchronization logic should not be scattered randomly throughout test cases. Common wait operations can be centralized into page objects or utility classes.

selenium_project/

|

+-- tests/

|   +-- test_login.py

|   +-- test_search.py

|   +-- test_cart.py

|

+-- pages/

|   +-- login_page.py

|   +-- search_page.py

|   +-- cart_page.py

|

+-- utilities/

|   +-- wait_helper.py

|   +-- screenshot_helper.py

|   +-- logger.py

|

+-- test_data/

|

+-- screenshots/

|

+-- reports/

|

+-- conftest.py

|

+-- requirements.txt

87. Recommended Wait Architecture

Test Case

    |

    v

Page Object

    |

    v

Wait Helper

    |

    v

WebDriverWait

    |

    v

Expected Condition

    |

    v

Web Application State

    |

    v

Element Ready

    |

    v

Perform Action

88. Waits with pytest Fixture

import pytest

from selenium import webdriver

from selenium.webdriver.support.ui import WebDriverWait

 

@pytest.fixture

def driver():

    browser = webdriver.Chrome()

    yield browser

    browser.quit()

 

@pytest.fixture

def wait(driver):

    return WebDriverWait(

        driver,

        10

    )

Using the Fixture

def test_login(driver, wait):

    driver.get(

        "https://example.com/login"

    )

 

    username = wait.until(

        EC.visibility_of_element_located(

            (By.ID, "username")

        )

    )

 

    username.send_keys("admin")

89. Waits and Test Assertions

A wait should synchronize the test before an assertion is performed.

dashboard = WebDriverWait(

    driver,

    10

).until(

    EC.visibility_of_element_located(

        (By.ID, "dashboard")

    )

)

 

assert dashboard.is_displayed()

The wait ensures the expected application state has been reached before the assertion checks the result.

90. Waits and Exception Handling

try:

    dashboard = WebDriverWait(

        driver,

        10

    ).until(

        EC.visibility_of_element_located(

            (By.ID, "dashboard")

        )

    )

 

    assert dashboard.is_displayed()

 

except TimeoutException:

    driver.save_screenshot(

        "dashboard_timeout.png"

    )

    raise

91. Waits and Screenshots

When a wait fails, a screenshot can provide useful information about the browser state at the time of failure.

try:

    WebDriverWait(

        driver,

        10

    ).until(

        EC.element_to_be_clickable(

            (By.ID, "checkout")

        )

    )

 

except TimeoutException:

    driver.save_screenshot(

        "checkout_wait_failure.png"

    )

    raise

92. Waits and Logging

import logging

 

logging.info(

    "Waiting for checkout button"

)

 

checkout = WebDriverWait(

    driver,

    10

).until(

    EC.element_to_be_clickable(

        (By.ID, "checkout")

    )

)

 

logging.info(

    "Checkout button is ready"

)

 

checkout.click()

93. Choosing the Correct Expected Condition

RequirementRecommended Condition
Element exists in DOMpresence_of_element_located()
Element is visiblevisibility_of_element_located()
Element should be clickedelement_to_be_clickable()
Multiple elements existpresence_of_all_elements_located()
All elements visiblevisibility_of_all_elements_located()
Loader disappearsinvisibility_of_element_located()
Text appearstext_to_be_present_in_element()
Page title changestitle_is() or title_contains()
URL changesurl_to_be() or url_contains()
Alert appearsalert_is_present()
Frame becomes availableframe_to_be_available_and_switch_to_it()
New window opensnumber_of_windows_to_be()
Old element disappears after DOM replacementstaleness_of()

94. Quick Revision Table

ConceptExamplePurpose
Implicit Waitdriver.implicitly_wait(10)Global element-location timeout.
Explicit WaitWebDriverWait(driver, 10).until(...)Wait for a specific condition.
PresenceEC.presence_of_element_located()Element exists in DOM.
VisibilityEC.visibility_of_element_located()Element is visible.
ClickableEC.element_to_be_clickable()Element is ready for clicking.
InvisibilityEC.invisibility_of_element_located()Element disappears or becomes invisible.
TextEC.text_to_be_present_in_element()Wait for specific text.
URLEC.url_contains()Wait for URL condition.
TitleEC.title_contains()Wait for title condition.
AlertEC.alert_is_present()Wait for alert.
FrameEC.frame_to_be_available_and_switch_to_it()Wait and switch to frame.
WindowsEC.number_of_windows_to_be()Wait for window count.
Stale ElementEC.staleness_of()Wait for old element to become stale.
TimeoutTimeoutExceptionHandle unsuccessful waits.

95. Interview Questions on Selenium Waits

Q1. What is a wait in Selenium?

A wait is a synchronization mechanism that allows Selenium to wait for an element or application condition before continuing execution.

Q2. What are the main types of waits?

The commonly discussed Selenium wait mechanisms are implicit waits, explicit waits, and fluent-style configurable waits.

Q3. What is an implicit wait?

An implicit wait sets a global timeout used when WebDriver searches for elements.

Q4. What is an explicit wait?

An explicit wait waits for a specific condition before allowing the script to continue.

Q5. What is WebDriverWait?

WebDriverWait is Selenium's Python wait utility for waiting until a condition succeeds or the timeout is reached.

Q6. What is Expected Conditions?

Expected Conditions are predefined conditions that can be used with explicit waits for common synchronization scenarios.

Q7. What is the difference between presence and visibility?

Presence means that the element exists in the DOM. Visibility means that the element exists and is visible on the page.

Q8. What is element_to_be_clickable()?

It is an expected condition used when an element needs to be visible and enabled for clicking.

Q9. What exception occurs when an explicit wait times out?

Selenium raises TimeoutException when the wait condition is not satisfied before the timeout.

Q10. Why should sleep() not be used everywhere?

sleep() waits for a fixed duration and does not check whether the application is already ready. Condition-based waits are generally more suitable for Selenium synchronization.

Q11. Can Selenium wait for text?

Yes. Expected Conditions provide text-related conditions such as text_to_be_present_in_element().

Q12. Can Selenium wait for a URL?

Yes. Conditions such as url_to_be() and url_contains() can be used.

Q13. Can Selenium wait for an alert?

Yes. EC.alert_is_present() can be used with WebDriverWait.

Q14. Can Selenium wait for a frame?

Yes. frame_to_be_available_and_switch_to_it() can wait for a frame and switch into it.

Q15. How can waits be reused in Page Object Model?

A reusable WebDriverWait object or wait helper class can be maintained inside page objects or utility classes.

Q16. What is polling frequency?

Polling frequency determines how frequently a wait checks the specified condition.

Q17. What is a timeout?

A timeout is the maximum period the wait is allowed to keep checking a condition before failing.

Q18. What is the difference between wait and assertion?

A wait synchronizes execution with application state, while an assertion verifies whether the actual result matches the expected result.


96. Recommended Selenium Wait Flow

Start Test

    |

    v

Open Application

    |

    v

Identify Required Element

    |

    v

Choose Locator

    |

    v

Choose Correct Wait Condition

    |

    v

Set Reasonable Timeout

    |

    v

Wait for Condition

    |

    v

Condition Satisfied?

   /          \

 Yes           No

 |              |

 v              v

Perform       Timeout

Action           |

                 v

          Capture Evidence

                 |

                 v

          Log Failure

                 |

                 v

             Raise Error

97. Professional Selenium Wait Strategy

Requirement

    |

    v

Identify Application State

    |

    v

Select Stable Locator

    |

    v

Select Appropriate Condition

    |

    v

Configure WebDriverWait

    |

    v

Wait for Condition

    |

    v

Perform Action

    |

    v

Validate Result

    |

    v

Continue Test

    |

    v

Cleanup

98. Final Summary

Waits are a fundamental part of reliable Selenium automation with Python. Web applications often contain dynamically loaded elements, asynchronous operations, animations, AJAX requests, overlays, frames, alerts, and changing page states. Selenium scripts therefore need synchronization mechanisms that respond to actual application conditions.

Implicit waits provide a global element-location timeout, while explicit waits allow the automation script to wait for specific conditions. WebDriverWait combined with Expected Conditions is particularly useful for dynamic web applications because it allows the test to wait for the state required by the next operation.

Common conditions include waiting for element presence, visibility, clickability, text, URL changes, title changes, alerts, frames, multiple windows, invisibility, and stale elements. Custom lambda conditions can also be used when a predefined condition does not represent the required application state.

Professional Selenium automation should avoid excessive fixed delays, use appropriate synchronization conditions, handle TimeoutException correctly, capture useful debugging information, and centralize reusable wait logic where appropriate.

The main goal of Selenium waits is to make automation stable, synchronized, reliable, readable, maintainable, and suitable for dynamic web applications.

99. Course Resources

Selenium Training: https://www.justacademy.co/course-detail/selenium-training

Register for Course Demo: https://www.justacademy.co/register-for-course-demo

whatsapp