Not sure what is causing selenium timeouts - python

So recently tried to create a suite in python to run tests on some twitter share buttons. I used the "switch_to_frame" function to navigate into the iframe and select the button. Here is my code
class EntertainmentSocialMedia(CoreTest):
def testEntertainmentTwitter(self):
d = self.driver
d.get(config.host_url + '/testurl')
social_text = 'Follow #twitterhandle'
print "Locating Entertainment vertical social share button"
time.sleep(3)
d.switch_to_frame(d.find_element_by_css_selector('#twitter-widget-0'))
social_button = d.find_element_by_xpath('//*[#id="l"]').text
self.assertTrue(str(social_text) in str(social_button))
print social_button
d.close()
My concern is that with multiple tests in the suite, sometimes selenium will timeout. Is there something wrong with my code or can it be improved? Ideally I'd like them to be as robust as possible and avoid timeouts. Thanks!

Better wait for the frame explicitly:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
...
d.get(config.host_url + '/testurl')
frame = WebDriverWait(d, 10).until(
EC.presence_of_element_located((By.ID, "twitter-widget-0"))
)
d.switch_to_frame(frame)
This would wait up to 10 seconds and then throw TimeoutException. By default, it would check the presence of frame every 500 ms.
Hope that helps.

Related

Cannot use WebDriverWait library properly in Python Selenium

Hello everyone I'm learning selenium recently and as I bet is a classic newbie mistake I filled my code with time.sleep which made everything really slow. So I started to learn about webdriverWait. I took some sample code and I have tried multiple things but I still get the error of "what you clicked is blocked by this other thing" meaning that the library did not crash but it also did not do anything. Which must mean I am doing something wrong. This is an error I can avoid if use the time.sleep function.
I'm using expected conditions, BY and action chains alongside WebDriverWait, though in my last test I tried to not use Acton chains to lower the possibilities of why its failing.
I'm using a company site that is probably under NDA so I don't have a public example to show this on, I tried searching for "pages with cover openings" but I couldn't find any, so if you guys know of any that I can use to illustrate this I would also find that really helpful. What is happening is that the site loads with a "cover" animation and after a few seconds the animation goes away to reveal the Button I'm looking for.
Environment info:
Using Pycharm community latest version
Using Selenium 4.0.0b2.post1 (I also tried in 3.9 to no results)
Using ChromeDriver 89 as my google chrome version is 89 as well [Version 89.0.4389.114 for Chrome]
Here are my code snippets:
Attempt #1:
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
import selenium.webdriver.support.expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
import selenium.webdriver.support.ui as ui
def test(driver, actions, delay):
cart = "//header/div[1]/div[1]/a[2]/*[1]"
cartxp = WebDriverWait(driver, delay).until(EC.visibility_of_element_located((By.XPATH, cart)))
actions.move_to_element(cartxp).perform()
cartclk = driver.find_element_by_xpath(cart).click()
Attempt #2: Using UI library
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
import selenium.webdriver.support.expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
import selenium.webdriver.support.ui as ui
def test2(driver, delay, actions):
cart = "//header/div[1]/div[1]/a[2]/*[1]"
cartxp = ui.WebDriverWait(driver, delay).until(EC.visibility_of_element_located((By.XPATH, cart)))
actions.move_to_element(cartxp).perform()
cartclk = driver.find_element_by_xpath(cart).click()
Attempt #3: Not using Action chains
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
import selenium.webdriver.support.expected_conditions as EC
from selenium.webdriver.common.by import By
def test3(driver, delay):
wait = WebDriverWait(driver, delay)
cart = "//header/div[1]/div[1]/a[2]/*[1]"
button = wait.until(EC.element_to_be_clickable((By.XPATH, cart)))
cartclk = driver.find_element_by_xpath(cart).click()
All of these have a main method that just has:
driver = webdriver.Chrome()
test3(driver, 30)
driver.get('Site that I cant reveal cuz of NDA')
action = ActionChains(driver)
The error I get is:
Message: element click intercepted: Element ... is not clickable at point (1183, 27). Other element would receive the click
Thanks in advance for any help!
Edit: After some comments changed my xpath to //a[#class='header__cart'] both the previous and this one leads to a single result If I use it on chrome inspect to look for the button, additionally it works as intended if I use it to actually click the button after using time.sleep() to wait out the animation
Additionally just in case tried using the try catch as they did on the suggested question. It also failed
Attempt 4: surrounding in a try-catch
def test4(driver, delay):
cart = "//a[#class='header__cart']"
try:
my_elem = WebDriverWait(driver, delay).until(EC.visibility_of_element_located((By.XPATH, cart)))
print
"Page is ready!"
except TimeoutException:
print
"Loading took too much time!"
cart_btn = driver.find_element_by_xpath(cart)
cart_btn.click()
Error: selenium.common.exceptions.ElementClickInterceptedException: Message: element click intercepted: Element <a href="/cart" class="header__cart" data-items-in-cart="0" )="">... is not clickable at point (1200, 27). Other element would receive the click
To clarify what I meant earlier this works:
cart = "//a[#class='header__cart']"
time.sleep(20)
cartclk = driver.find_element_by_xpath(cart).click()

Unable to input values fully in a text field using send keys. Only partial values entered and no error shown

Unable to input values fully in a textbox field using send keys. Only partial values entered and no error shown.
Attempted sending keys with a wait.
Attempted sending keys slowly.
[Edit] - This is the entire script as requested in the comments below
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.wait import WebDriverWait
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
import time
from time import sleep
from selenium.webdriver.common.keys import
Keysdriver=webdriver.Chrome(executable_path="C:\Program Files (x86)\Drivers\chromedriver.exe")
driver.get("https://www.volunteers.ae/register.aspx")
driver.find_element_by_xpath("//*[#id='topnav_btnLangShift']").click()
driver.find_element(By.ID,'body_txtFName').send_keys("RADHIKA")
driver.find_element(By.ID,'body_txtLName').send_keys("PORANKI")
driver.find_element_by_id("body_txtEmail").send_keys("radhika.po#gmail.com")
element=driver.find_element_by_id("body_ddGender")
dropdown=Select(element)dropdown.select_by_value("Female")
driver.find_element_by_id("ctl00_body_txtDOB_dateInput").send_keys("08/04/1986")
element=driver.find_element_by_id("body_ddNationality")
dropdown=Select(element)
dropdown.select_by_value("India")
element=driver.find_element_by_id("body_ddCountryOfResidence")
dropdown=Select(element)
dropdown.select_by_value("+971")
element=driver.find_element_by_id("body_ddEmirate")
dropdown=Select(element)
dropdown.select_by_value("DUBAI")
time.sleep(10)
element=driver.find_element_by_id("body_ddCity")
dropdown=Select(element)
dropdown.select_by_value("DUBAI CITY")
def ClickAndSlowType(element, text):
element.click()
sleep(1) # let scripts run
for t in list(text):
print(t)
element.send_keys(t)
sleep (0.1)
mobile = WebDriverWait(driver, 8).until(ec.element_to_be_clickable((By.XPATH, "//*[#id='ctl00_body_txtEtisalat']")))
mobile.click()
mobile.send_keys("68862632")
What's the problem when you run your script?
I enhanced your script with a wait action and it works great:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get('https://www.volunteers.ae/register.aspx')
mobile = WebDriverWait(driver, 8).until(EC.element_to_be_clickable((By.XPATH, "//*[#id='ctl00_body_txtEtisalat']")))
mobile.click()
mobile.send_keys("68862632")
Output looks like this:
There does seem to be some scripting at work in the page. Evertyime you click and type it resents the field. However, the above code still seems to work.
If there's a problem, let me know what's happening (with any relevant errors that occur) and i'll look again.
[Update!]
Based on the comments below, try typing with a delay.
Add this import:
from time import sleep
Add this function:
def ClickAndSlowType(element, text):
element.click()
sleep(1) # let scripts run
for t in list(text):
print(t)
element.send_keys(t)
sleep (0.1)
Run this:
mobile = WebDriverWait(driver, 8).until(EC.element_to_be_clickable((By.XPATH, "//*[#id='ctl00_body_txtEtisalat']")))
ClickAndSlowType(mobile, "68862632")
I can't recreate your issue but this also works for me so worth a try. It just types a bit slower in case of the funky in-page script issues.
Let me know how it goes.
If you can update your question with your entire i code i might be able to recreate and provide a tried and tested answer. (no one likes "it worked for me")
As it works locally but not on #Paul 's machine : we need to debug it . Try this at the end of the script and please tell exactly what you see happen to the field and what the output from the prints on the console:
def WaitForDocumentReadyState():
print("Ready State Before: " + driver.execute_script('return document.readyState'))
WebDriverWait(driver, 10).until(lambda driver: driver.execute_script('return document.readyState') == 'complete')
def ClickAndSlowType(element, text):
element.click()
WaitForDocumentReadyState()
sleep(1) # let scripts run
for t in list(text):
element.send_keys(t)
WaitForDocumentReadyState()
sleep (0.5)
sleep(1) # let scripts run
WaitForDocumentReadyState()
mobile = WebDriverWait(driver, 8).until(ec.element_to_be_clickable((By.XPATH, "//*[#id='ctl00_body_txtEtisalat']")))
#mobile.click()## REMOVED
#mobile.send_keys("68862632") ## REMOVED
ClickAndSlowType(mobile, "68862632") ## using the function

Python Selenium: waiting isn't waiting

I'm designing a web scraper. At a few points I need it to wait for around 10 seconds before jumping to the next action to account for internet connection problems. I want to have a simple implicit wait.
driver.get('MY WEBSITE')
driver.implicitly_wait(10)
menu = driver.find_element_by_link_text("Export")
menu2 = driver.find_element_by_xpath('//td[text()="Data"]')
actions = ActionChains(driver)
actions.move_to_element(menu)
actions.click(menu)
actions.move_to_element(menu2)
actions.click(menu2)
actions.perform()
The only problem is: it's not waiting. I've even tried putting 20 and more secs as the implicitly_wait parameter in order to be completely sure and there was no change. It's opening the website and going directly to search for the two elements. Can anyone explain that please?
From the docs:
An implicit wait tells WebDriver to poll the DOM for a certain amount of time when trying to find any element (or elements) not immediately available. The default setting is 0. Once set, the implicit wait is set for the life of the WebDriver object.
So if the element is immediately available, it won't wait.
Try to use WebDriverWait :
E.g
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.Firefox()
driver.get("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()

Wait time between each action

Hello I am new to python and I am trying to create an automation bot (I am very new to python) that logs into instagram and likes a certain number of posts but I am trying to figure out how to add a delay from when it enters the username information and password but I am not sure how to go about that, Also I would appreciate any feedback/recommendations thank you. Here is the code I have so far
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
browser = webdriver.Chrome()
def site_login():
browser.get('https://www.instagram.com/')
browser.find_element_by_name("username").send_keys(‘username’)
browser.find_element_by_name("password").send_keys(“password”)
browser.find_element_by_name("Log In").click() #not sure if this works
The time module should help you
import time
time.sleep(seconds) #Enter the time in seconds here
If you want to wait for a specified period then you can use time.sleep(timeInSeconds) which need import time.
import time
time.sleep(number_of_seconds)
But, however I would like to use the explicit wait. Unlike hard timeout, this will wait until the condition is met and continue the script.
# needed the imports
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
# wait for the element and click (using xpath locator)
WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.XPATH, "xpath_goes_here"))).click()
# wait for the element and enter value (using css locator)
WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "css_locator_goes_here")))).send_keys("enter input")
# store the element and then perform action
loginButton = WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "css_locator_goes_here"))))
loginButton.click()
you can use either CSS or xpath location strategy.
You can also use implicit wait at the driver level by adding below line of code.
browser.implicitly_wait(10)
Instead of using time.sleep(seconds) , I would recommend to use Explicit wait as the previous comment. Since due to environment changes time can be vary. So its better to use Explicit wait. Using time.sleep(seconds) will sleeps the current thread. It's a bad practice.
Thanks

Python selenium: wait until element is clickable - not working

I will test a web-app. there is a button available in my table to select all entries.
I've tried:
driver.wait.until(ExpectedCondition.element_to_be_clickable((By.XPATH, "myXpath"))).click()
selenium clicks on the button, but nothing happens. (also with send_Keys(Keys.Return)) the application is developed with GXT, I thing that there is much javascript behind the button. Is there is possibility to wait until a eventloader is ready? waiting before a click solves the problem, but not a solution for automated testing.
Correct syntax for explicit wait in python is :
element = WebDriverWait(driver, 20).until(
EC.presence_of_element_located((By.ID, "myElement")))
Better that After above you do :
element.click();
So in your case :
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
element = WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.XPATH, "myXpath")))
element.click();
Better you follow it. Also share your whole code so I can correct it. Your just 1 line code doing little confuse.
I had also that problem... Web apps have views over views and Appium sometimes gets wrong.
This worked for me:
x = webElement.location['x'] + (webElement.size['width']/2)
y = webElement.location['y'] + (webElement.size['height']/2)
print("x: "+x+" - y: "+y)
//I have setted a 200 milli duration for the click...
//I use tap just for Android... If is iOS for me it works better touchAction
driver.tap([(x,y)], 200)
Edit:
I misunderstood your question... Sorry...
Maybe modifying your Xpath to:
(don't know if this will work at a web app)
xpath = "//whatever_goes_here[#clickable='true']"
I know it is probably too late, but for me the solution was to add this line before all the elements clicks:
driver.execute_script('document.getElementsByTagName("html")[0].style.scrollBehavior = "auto"')
Nowadays, sites tend to have a scrholl-behavior set to auto. Drivers do not know that, though they do know when an element is outside the view. So, what happens is a driver tries to click the element. The driver sees that the element is outside the view, so it calls a scroll method and after that immediately clicks the element without waiting for scrolling to finish. And the scrolling does take some time because of its behavior set to auto.
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait=WebDriverWait(driver,5)
a= wait.until(EC.element_to_be_clickable(('id or xpath or class or any thing else ','enabled_trigger')))
a.click()
please note you must have two parentheses in element.to_be_clickable(())

Categories