Recently I came to an issue of needing to wait for an element to load. Selenium does have a WebdriverWait that will wait for an item to load. However it doesn’t have the capability of conditional logic, i.e. “selenium wait for element, if it’s not loaded after waiting expires, then do something else.” This is a assertion of selenium, in the end it’s a pass or fail.

In a case where you may have A/B testing going on, where 30% of the time, a different page loads… or where you have a 3rd party application that might not load correctly, you may need to find work arounds.

Note: In general, working around a failure, is not a good idea. It’s better to report the problem, so it can be corrected. However, in the real world, there are use cases, where we do need to work around random outages. Examples of this would be building bots for games (grey area automation), or in a better ethical scenario, you might be testing a phone call across multiple carriers, and one carrier is failing 1 out of 100 times. To flag that call as a fail, would likely be considered a false flag. While testing the carrier capabilities is good (and a separate test), to know if a call completes, it might be better to rerun the test on each fail.

In my case, I was using Appium on a form submit. My local environment was very slow, and sometimes it took over 45 seconds to get the form to submit to the database. Of course I let people know about it, in the hopes of resolution. In the meantime, I decided to build a work around.

Selenium can wait for an element, like so:

WebDriverWait(browser, 20).until(EC.presence_of_element_located((By.CSS_SELECTOR, ".thank_you"))).click()

This is an assertion. If after the specified time (20), the element still isn’t loaded, the test will fail the assertion and it will end. You may be able to finagle keeping the test running, but it’s not a clean way to handle conditional logic.

In my case I decided to use Regex, because Regex will allow me to wrap conditional logic around it… in other words, if something is there, continue on with the test, if it isn’t there, wait longer or do some other logic.

I gave an example as an answer on Stack Overflow. In my personal case, I used the following to keep waiting for an element, without invoking selenium:

import re
from appium import webdriver

# Setting up the driver and capabilities:
caps = {}
caps["deviceName"] = "emulator-5554"
caps["platformName"] = "android"
caps["browserName"] = "Chrome"
caps["chromedriverExecutable"] = "/Users/bwarner/webdrivers/chromedriver83"
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", caps)

# Example code where something is submitted:
elem_reg_submit.click()
recursiveWait(driver, "Thank You!")
driver.get("https://....")

# Conditional wait example, using Regex:
def recursiveWait(driver, text):
    src = driver.page_source
    text_found = re.search(r'%s' % (text), src)
    print("checking for text on page...")
    if text_found:
        return
    else:
        print("not found. sleep 5 seconds")
        time.sleep(5)
        recursiveWait(driver, text)

In the case above, I have a case where I submit a form, then after getting to the Thank You page.

Since the submission of the form can take a random amount of time in the test env. waiting for an element to load may time out. In fact it may take so long the browser times out and redirects the user to the login page. In which case, I need conditional logic to address that.

#

No responses yet

Leave a Reply

Your email address will not be published. Required fields are marked *

Archives
Categories