How I can solve this Selenium If Elif problem? - python

I made a code to scrape some website. A list of IDs is iterated in the website, and it contains two conditions(If and Elif). But the problem is with the Elif. The error is it doesn't found the elif element (elem2).
I read in this question Python if elif else can't go to the elif statement Selenium the solution is a try/except, butI already used a Try/except to make works the if statement. What is a solution to make this code works with two conditions?
The code looks like this:
for item in list:
input = driver.find_element(By.ID, "busquedaRucId")
input.send_keys(item)
time.sleep(2)
elem1 = driver.find_element(By.ID, 'elem1')
elem1_displayed = elem1.is_displayed()
elem2 = driver.find_element(By.ID, 'elem2')
elem2_displayed = elem2.is_displayed()
try:
if elem1_displayed is True:
code to scrape given de first condition
elif elem2_displayed is True:
code to scrape given de second condition
except NoSuchElementException:
input = driver.find_element(By.ID, ('busquedaRucId')).clear()
Than you for any help. I'm stuck with this problem for two weeks.

I would restructure your code by wrapping the find_element function in a function which handles NoSuchElementExceptions by returning False, basically making the error silent:
def element_exists_and_displayed(driver, id):
try:
return driver.find_element(By.ID, id).is_displayed()
except NoSuchElementException:
return False
for item in list:
input = driver.find_element(By.ID, "busquedaRucId")
input.send_keys(item)
time.sleep(2)
if element_exists_and_displayed(driver, 'elem1'):
# code to scrape given first condition
pass
elif element_exists_and_displayed(driver, 'elem2'):
# code to scrape given second condition
pass
else:
driver.find_element(By.ID, ('busquedaRucId')).clear()

Related

Selenium Timeout - Expected Condition returning False

I'm coding a bot in Python that plays tic-tac-toe. The game is a Web app written in React.js and is equipped with an AI of its own that utilizes minimax. The user (which the Python bot simulates) is always X, the AI is always O, and the user always moves first. The Python bot plays by randomly selecting unmarked squares (this is only to demonstrate automated UI testing).
I was getting stuck inside a recursive function.
for loop and recursive call:
for i in clickedSquares:
if not winner:
self.checkForWinner(load_browser, winner)
elif i == random_square:
self.test_playTTT(load_browser)
else:
clickedSquares.append(random_square)
To fix this issue I added the if not winner condition where "winner" is a string. This does terminate the loop; however, I'm getting an error as soon as the checkForWinner() function is called because winnerOh is always false.
winnerOh = WebDriverWait(load_browser, 10).until(EC.presence_of_element_located((By.XPATH, Tags.resultOh)))
winnerEx = WebDriverWait(load_browser, 10).until(EC.presence_of_element_located((By.XPATH, Tags.resultEx)))
tiedGame = WebDriverWait(load_browser, 10).until(EC.presence_of_element_located((By.XPATH, Tags.resultTie)))
I'm looking for an element on the UI that declares the winner: X or O or tie, which will only appear if the game is over. So WebDriverWait().until() is timing out waiting for that element to appear, but it hasn't yet, because it's only the second move in the game.
I'm not sure how to fix this issue. If I remove the call to checkForWinner() the bot will get stuck in the recursive call to test_playTTT(). The browser will not close after the game is over, and the test will not end successfully.
Is there another way to check the UI for the element I'm looking for that won't immediately return a False condition? Is there a better way for me to write this for loop?
Included below is the full Python method.
class TestCase_PlayRandom():
URL = "http://localhost:3000"
#pytest.fixture
def load_browser(self, browser):
browser.get(self.URL)
yield browser
def test_playTTT(self, load_browser):
squares = [Tags.square1,Tags.square2,Tags.square3,
Tags.square4,Tags.square5,Tags.square6,
Tags.square7,Tags.square8,Tags.square9]
clickedSquares = []
random_square = randint(0,8)
time.sleep(5)
winner = ''
if not clickedSquares:
element = load_browser.find_element(By.XPATH, squares[random_square])
element.click()
clickedSquares.append(random_square)
for i in range(0,9):
if squares[i] == Tags.ohSquare:
clickedSquares.append(i)
for i in clickedSquares:
if not winner:
self.checkForWinner(load_browser, winner)
elif i == random_square:
self.test_playTTT(load_browser)
else:
clickedSquares.append(random_square)
element = load_browser.find_element(By.XPATH, squares[random_square])
element.click()
def checkForWinner(self, load_browser, winner):
winnerOh = WebDriverWait(load_browser, 10).until(EC.presence_of_element_located((By.XPATH, Tags.resultOh)))
winnerEx = WebDriverWait(load_browser, 10).until(EC.presence_of_element_located((By.XPATH, Tags.resultEx)))
tiedGame = WebDriverWait(load_browser, 10).until(EC.presence_of_element_located((By.XPATH, Tags.resultTie)))
if winnerOh:
winner = 'O'
LOGGER.info('Winner O')
return winner
elif winnerEx:
winner = 'X'
LOGGER.info('Winner X')
return winner
elif tiedGame:
winner = 'None'
LOGGER.info('Tie')
return winner
Try this:
def checkForWinner(self, load_browser, winner):
winnerOh = WebDriverWait(load_browser, 10).until(EC.invisibility_of_element_located((By.XPATH, Tags.resultOh)))
winnerEx = WebDriverWait(load_browser, 10).until(EC.invisibility_of_element_located((By.XPATH, Tags.resultEx)))
tiedGame = WebDriverWait(load_browser, 10).until(EC.invisibility_of_element_located((By.XPATH, Tags.resultTie)))
if not winnerOh:
winner = 'O'
LOGGER.info('Winner O')
return winner
elif not winnerEx:
winner = 'X'
LOGGER.info('Winner X')
return winner
elif not tiedGame:
winner = 'None'
LOGGER.info('Tie')
return winner
invisibility_of_element_located() will return True if the element is not found on the UI and False if it is.
You'll need to play with where to put the call to the function. I'd place it above the for loop instead of in it.

Creating a try and except statement that will try multiple conditions

while True:
try:
element = driver.find_element(By.XPATH, "//*[contains(#href,'dawson')]")
element.click()
break
except NoSuchElementException:
driver.refresh()
time.sleep(3)
Above is the try and except block that looks for a word in a Href and if it contains it the element is clicked. I wish to go through multiple of these given words and try them. So if the first word is not found it then goes on to the next word. It does not matter if it refreshes in between I just want it to iterate through these words and if it finds one it will click. How can I add more words into the try block?
Any help would be great.
Thank you
Search for an element in separate loop
def find_link_by_word_in_href(driver, words):
for word in words:
try:
return driver.find_element(By.XPATH, f"//*[contains(#href,'{word}')]")
except NoSuchElementException:
pass
while True:
element = find_link_by_word_in_href(driver, ['dawson', 'denbigh', 'and_so_on'])
if element is not None:
element.click()
break
else:
driver.refresh()
time.sleep(3)

trying to use continue or pass inside while loop but it doesnt seem to do work selenium

my program iterate between items, it clicks on the item, then clicks again and moves to the next item.
i am trying to make the program pass on an item if error accurs.
the excepts are inside a while loop, each item code seems like this:
item_1 = driver.find_element_by_id('feed_item_0')
item_1.location_once_scrolled_into_view
if item_1.is_displayed():
item_1.click()
time.sleep(2)
phone_reveal_1 = driver.find_element_by_id('phone_number_0')
contact_seller_1 = driver.find_element_by_id('contact_seller_0')
if phone_reveal_1.is_displayed():
phone_reveal_1.click()
elif contact_seller_1.is_displayed():
contact_seller_1.click()
elif not phone_reveal_1.is_displayed() or contact_seller_1.is_displayed():
continue
at the end i wrote this:
except selenium.common.exceptions.NoSuchElementException:
continue
except selenium.common.exceptions.ElementClickInterceptedException:
continue
except selenium.common.exceptions.StaleElementReferenceException:
continue
so what the code does is when any error accurs no matter if continue, or pass is written, the loop starts all over again from the start. i just want it to skip the item what. am i missing?
for anyone who will have the same issue, problem, was that i have handled the exceptions at the end. every block needs to have its own exception. the code should be like this:
try:
item_1 = driver.find_element_by_id('feed_item_0')
item_1.location_once_scrolled_into_view
if item_1.is_displayed():
item_1.click()
time.sleep(2)
phone_reveal_1 = driver.find_element_by_id('phone_number_0')
contact_seller_1 = driver.find_element_by_id('contact_seller_0')
if phone_reveal_1.is_displayed():
phone_reveal_1.click()
elif contact_seller_1.is_displayed():
contact_seller_1.click()
phone_numbers_1 = driver.find_elements_by_id('phone_number_0')
number_1 = [i.text for i in phone_numbers_1]
except NoSuchElementException:
pass

selenim web driver python repet code ultimate

how repeat code again again again this every work
I want the code below to always work and it should be repeated, and again this function should be repeated and not removed from the program.
def ref(self):
driver = self.driver
nextB2 = driver.find_element_by_xpath("""//section/span/button/span[#aria-label='Like']""")
nextB2.click()
time.sleep(5)
nextB3 = driver.find_element_by_xpath("""//section/span/button/span[#aria-label='Like']""")
nextB3.click()
time.sleep(6)
nextB4 = driver.find_element_by_xpath("""//section/span/button/span[#aria-label='Like']""")
nextB4.click()
time.sleep(7)
driver.refresh()
time.sleep(5)
driver.switch_to_frame('ref')
driver.refresh('ref')
you can use for loop with range to stop at perticular count like
for i in range(10): #10 times
ref() #function call
if you want it to run for ever
while True: #loop that never stops
ref()
you can use break and continue for conditional breaks
while True:
if foo == foo:
break #break or stop the while oop
elif foo == bar:
continue #skip current iteration and continue execution
else:
ref()

Using Python bindings, Selenium WebDriver click() is not working sometimes.

I am trying to submit an input(type= button).But I am unable to update the value.
Any help is appreciated.
I have attached the testcase below for your reference.
search for CLICK FAILS HERE
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
import unittest, time, re,datetime,os,sys
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
def is_element_present(inst,selector,value):
try:
inst.find_element(by=selector, value=value)
return True
except:
return False
class Testing(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(5)
self.base_url = "http://new.ossmoketest.appspot.com/"
self.verificationErrors = []
def test_ing(self):
try:
driver = self.driver
driver.get(self.base_url + "/Apab4b39d4_09d7_11e1_8df9_139372201eeb/1/signin?forward=/%3F")
now = datetime.datetime.now()
start = time.clock()
for i in range(5000000):
try:
if is_element_present(driver,By.ID,"userid"): break
except: pass
else: self.fail("time out")
end = time.clock()
diff = end - start
print diff
driver.find_element_by_id("userid").clear()
driver.find_element_by_id("userid").send_keys("senthil.arumugam#orangescape.com")
driver.find_element_by_xpath("//input[#src='/static/images/signup.png']").click()
print 'finished'
start = time.clock()
for i in range(5000000):
try:
if is_element_present(driver,By.LINK_TEXT,"Logout"): break
except: pass
else: self.fail("time out")
end = time.clock()
diff = end - start
print diff
time.sleep(5)
start = time.clock()
name = "smoketest"+ str(now.minute) +str(now.second)
for i in range(5000000):
try:
if is_element_present(driver,By.LINK_TEXT,"PurchaseOrder"): break
except: pass
else: self.fail("time out")
end = time.clock()
diff = end - start
driver.find_element_by_link_text('PurchaseOrder').click()
name = "smoketest"+ str(now.minute) +str(now.second)
start = time.clock()
for i in range(5000000):
try:
if is_element_present(driver,By.ID,"Customer_Name"): break
except: pass
else: self.fail("time out")
end = time.clock()
diff = end - start
newproduct = "rexona"+ str(now.minute) +str(now.second)
newprice = str(now.minute) +str(now.second)
newprice = float(newprice)
print newprice
driver.find_element_by_xpath("//input[starts-with(#id,'New_Product')]").send_keys(newproduct)
driver.find_element_by_xpath("//input[starts-with(#id,'Price')]").clear()
time.sleep(3)
driver.find_element_by_xpath("//input[starts-with(#id,'Price')]").send_keys(Keys.CONTROL+'a'+Keys.NULL, str(newprice))
Mouse_cntrl = ActionChains(driver)
Mouse_cntrl.release(driver.find_element_by_xpath("//input[starts-with(#id,'Price')]"))
value = newprice
print value
time.sleep(2)
print 'start'
print driver.find_element_by_xpath("//input[starts-with(#id,'NewItem_NewItem')]").get_attribute('data-id')
# ------------------------CLICK FAILS HERE ------------------------------
# driver.find_element_by_xpath("//input[starts-with(#id,'NewItem_NewItem')]").click()
# driver.find_element_by_xpath("//input[starts-with(#id,'NewItem_NewItem')]").submit()
driver.find_element_by_xpath("//input[starts-with(#id,'NewItem_NewItem')]").send_keys(keys.ENTER)
# Mouse_cntrl.double_click(driver.find_element_by_xpath("//input[starts-with(#id,'NewItem_NewItem')]"))
for i in range(10):
try:
print driver.switch_to_alert().text
if driver.switch_to_alert():
driver.switch_to_alert().accept()
break
except: pass
time.sleep(1)
else:
print "alert not found"
print 'finished -- '
time.sleep(8)
driver.find_element_by_xpath("//input[starts-with(#id,'Product')]").click()
arg = newproduct
print 'end'
for i in range(60):
try:
if is_element_present(driver,By.LINK_TEXT,arg): break
except: pass
time.sleep(1)
else: self.fail("time out")
# sel.mouse_over("//html/body/ul/li/a[.=\""+arg+"\"]")
driver.find_element_by_link_text(arg).click()
start = time.clock()
time.sleep(25)
for i in range(1000000):
try:
if newprice == float(driver.find_element_by_id('Unit_Price').text):
end = time.clock()
diff = end - start
log.log(module='Smoke',testcase='Action New', result='Pass',time_taken= diff)
break
except: pass
else:
log.log(module='Smoke',testcase='Action New', result='Fail')
self.fail('New Failure')
log.log(module='Smoke',testcase='On Submit', result='Pass',time_taken= diff)
driver.find_element_by_id('Quantity').send_keys(Keys.CONTROL+'a'+Keys.NULL,"1")
time.sleep(5)
start = time.clock()
for i in range(1000000):
try:
if value == float(driver.find_element_by_id('Unit_Price').text):
end = time.clock()
diff = end - start
log.log(module='Smoke',testcase='Multiply', result='Pass',time_taken= diff)
break
except: pass
else: self.fail("time out")
for i in range(1000000):
try:
if value == float(driver.find_element_by_id('Amount').text):
end = time.clock()
diff = end - start
log.log(module='Smoke',testcase='DSUM with Parent', result='Pass',time_taken= diff)
break
except: pass
else:
end = time.clock()
diff = end - start
log.log(module='Smoke',testcase='DSUM with Parent', result='Fail',time_taken= diff)
self.fail("time out")
except:
self.driver.quit()
e = sys.exc_info()[1]
print str(e)
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)
if __name__ == "__main__":
unittest.main()
It has been a showstopper for my work. Any help is appreciated.Thanks
You could try substituting .click() with .send_keys("\n"), which is equivalent to "Pressing enter while focusing on an element".
So this:
driver.find_element_by_link_text('PurchaseOrder').click()
would become this:
driver.find_element_by_link_text('PurchaseOrder').send_keys("\n")
In case this is still a recurring problem for anyone else, if you have confirmed your code is correct (you've reviewed it for errors etc.) and you still find the find_element_by_...('text').click() function not working properly it is often due to your code continuing to run before the JavaScript can update the page.
A simple solution is to import time then insert the below code immediately after any click() methods:
time.sleep(2)
The duration of the sleep timer can be whatever you choose. In my case I used 2 seconds. Hopefully that helps.
I had this problem as well. Sometimes, for whatever reason webdriver didn't click the button. It was able to find the button (it didn't throw a NoSuchElementException and a WebDriverWait didn't help).
The problem with clicking the button twice was that if the first click succeed, the second one would fail (or click the submit button on the next page if it found a match!). My first attempt was to put the second click in a try/except block - this is how I found out about it clicking submit on the next page. XD And it also really slowed down my test when it couldn't find the second button.
I found some good insights at Selenium 2.0b3 IE WebDriver, Click not firing. Basically, I click on a parent element first, which seemingly does nothing. Then I click on the submit button.
If the element you click() is an url. I found that taking the href properties and using driver.get(elem.get_attribute('href')) being the cleanest.
I would try other element finders like className, cssSelector or something. xPath sometimes doesnt provide errors if the element isn't found.
So first start by finding out if the element is really found by webdriver.
You can also try to click or use the other commands two times in a row. This already solved some of such issues.
I had the same issue where a two-part drop down menu selection would not generate what it's supposed to generate with proper selections. It worked when I did imported time and use time.sleep(2) between the two "click"s. (For reference I used find_element_by_xpath to find an modify the options.)
I ran into the above issue where the same .click() is working in all browsers(IE, Chrome and Firefox) but not working for Safari. So I tried all the possible solutions from this post and none of them worked and it doesn't even throw error.
I tried below by substituting .click() with .submit(), which is an equivalent method and it worked not only for Safari but also for all other browsers.
So this:
driver.find_element_by_id('login_btn').click()
Replaced as:
driver.find_element_by_id('login_btn').submit()
If above fails to work on other browsers due to any reason keep .submit() in try and except. If it fails .click() will be triggered and executed.
Hope this helps if none of the other solutions works.
For those, click() doesn't work, use submit() if that button element(clickable element) is in a form element. Basically, in order to submit a form, we need to use submit(), click() will not work in some cases.
I foolishly did elem.click with the parentheses: elem.click().

Categories