How do i wait for element on screen to be displayed? (python)

Hi,

I am trying to automate an android app using Python. I am having issues regarding some elements not being found in app or not yet active. I’m getting python error that element is not accessible which basically means it cannot find it in app. For example, here is a little snippet of code:

button = driver.find_elements_by_class_name(“android.widget.Button”)
#Tap on button
action = TouchAction(driver)
action.tap(button[0]).perform()

So basically i am trying to tap on a button but I need to tap button only after it is active. Does anybody know what API or code i can use to implement this?

Another example in my code is this:

EditText[0].send_keys(sh.cell_value(row+1,1))
driver.press_keycode(66)
 #Grab the data in text field that contains intention value
text = driver.find_elements_by_class_name("android.widget.TextView")

In this case, i basically can’t grab the text value from “android.widget.TextView” since it takes time to load after i submit my input. I tried driver.implicitly_wait(10) which shoudl wait 10 seconds for the element but it didn’t work. Anybody have any ideas?

Thanks in advance,

Jonathan

in ruby I use

wait { button_exact('my_button').click }

Its ugly, but you can also use a while and change the count limit and sleep, like

count = 0
while buttons('my_button').size == 0 and count < 10 do
   sleep 0.5
   count += 1
end
1 Like

Code all of your tests with explicit waits whenever the AUT is going to be processing something. Here’s a function I culled from someone else, you can just pass it xpath to your element, and a timer so that it doesn’t wait forever and get stuck in an infinite loop.

I also have other custom functions that wait for groups of elements, wait for dialogs to close (no longer be found), and whatever else you need. But always explicitly wait, it’s much more robust. Once your tests are functioning reliably with explicit waits you can then pad the whole test suite with a small implicit wait if you want to add in a small 1-5 second wait to help ensure minor timing issues don’t cause failures.

#
"""An explicit waits is code you define to wait for a certain condition to occur before proceeding further in the
code. The worst case of this is time.sleep(), which sets the condition to an exact time period to wait. There are
some convenience methods provided that help you write code that will wait only as long as required. WebDriverWait
in combination with ExpectedCondition is one way this can be accomplished."""
# wait_time has a default value of 120 seconds (common backend timeout) unless user supplies their own custom value
def explicitly_wait_for(self, wait_time=120):
    print "Explicitly waiting for element ", self.locator
    return WebDriverWait(self.driver, wait_time).until\
        (expected_conditions.presence_of_element_located((By.XPATH,self.locator)))

Thanks Christopher! Just has a couple of questions.

Is there any import statements i need to add to code for this function to work? Right now i’m looking for elements by class name. How can i find the xpath for an element?

Once I have answer to these questions, i’ll try to use this function and let you know how it goes.

Thanks again!

# Next 3 imports are just for enabling 'explicitly_wait_for'
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.common.by import By

I’m assuming you can change “By.XPATH” to “By.CLASS_NAME”. If you use an IDE like PyCharm for development it will help you craft includes and provide automated code-completion to help you along the way.

Note I’m not a coding expert at this point so there’s likely faster / better ways to approach this. I’m just sharing what I have working for me in hopes it benefits others.

I also have a bunch of custom functions in my page objects that allow me to determine if a particular dialog is open by querying the UI for specific elements. Here’s one example for determining if a Login dialog is open, I’m sure there’s shorter ways to code these but it’s functional. Just change the locator strategy to whatever you’re using.

def is_login_dialog_open(self):
    try:
        # Validate login dialog is present by checking for all of it's elements
        self.assertIsNotNone(self.driver.find_element_by_xpath(self.username_field.locator))
        self.assertIsNotNone(self.driver.find_element_by_xpath(self.password_field.locator))
        self.assertIsNotNone(self.driver.find_element_by_xpath(self.login_button.locator))
        self.assertIsNotNone(self.driver.find_element_by_xpath(self.cancel_button.locator))
        self.assertIsNotNone(self.driver.find_element_by_xpath(self.forgot_password.locator))
        self.assertIsNotNone(self.driver.find_element_by_xpath(self.create_new_account.locator))
        self.assertIsNotNone(self.driver.find_element_by_xpath(self.background.locator))
        # print "Login Dialog exists = True"
        return True
    except:
        # print "Login Dialog exists = False"
        return False

I then have other functions that leverage that to cause the scripts to explicitly wait for the Login dialog to physically open before proceeding, but with a timeout to prevent infinite loops:

# wait_time has a default value of 15 seconds unless user supplies their own custom value
def wait_for_login_dialog_to_open(self, wait_time=15):
    print "Waiting for Login dialog to open, max wait =", wait_time, "seconds"
    timeout = time.time() + wait_time   # Timer based on wait_time to prevent infinite loops
    while True:
        time.sleep(1)   # Prevent CPU slamming with short timeout between loops
        if time.time() > timeout:
            print "Warning! Did not find Login dialog in", wait_time, "seconds"
            break
        if self.is_login_dialog_open:   # If the Login dialog is_login_dialog_open or timer expires
            print "Login dialog open, proceeding"
            break

Hi friend
how can i say appium webdriver to wait untill my copy process gets completed in python script

Please help

One of the benefits of using appium webdriver, is you can use your selenium code. ‘WebDriverWait’ is an explicit wait, which you can learm more about here: http://selenium-python.readthedocs.io/waits.html?highlight=webdriverwait

So for example in python 3.x you can use ‘WebDriverWait’, to wait for a mobile app to load the login page, as in the following example:

from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

    desired_caps = {}
    desired_caps['platformName'] = 'Android'
    desired_caps['platformVersion'] = '6.0'
    desired_caps['deviceName'] = 'Android Emulator'
    desired_caps['app'] = 'C:\\test\\TimeWorksMobile.apk'
    driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)


    WebDriverWait(driver, 30).until(EC.presence_of_element_located((By.ID, "Username")))
    driver.find_element_by_accessibility_id("Username").clear()
    driver.find_element_by_accessibility_id("Username").send_keys("testuser")
4 Likes

Thanks @webcrew. Your solution helped me.