I am trying to verify if a row is displayed or not. I am using python and Selenium. Here is what I have tried so far
try:
row = self.driver.find_element_by_xpath(<row6>).is_displayed()
if row is False:
print("button is not displayed. Test is passed")
else:
do stuff
except:
NoSuchElementException
I am trying to achieve the following:
Page #1 will only display a button if Page #2 has row < 6.
I still have logic to write for the condition -> if row is False: . However, it should atleast print the string if it is false.
At the moment, the else: in my code is not working. There is no error displays but try: exits at the NoSuchElementException.
UPDATE: I have also tried the following code where I verify if button is displayed on page #1, go to the page #2 and validate if row6 is present. That works if button is displayed. If button is not displayed, it throws an error :NoSuchElementException: Message: Unable to locate element:
try:
button = self.driver.find_element_by_xpath(PATH)
if button.is_displayed():
do stuff
row = self.driver.find_element_by_xpath(<row6>)
if row.is_displayed():
do stuff
else:
do stuff
except:
button = self.driver.find_element_by_xpath("PATH").is_displayed()
if button is False:
print("button is hidden. Test is passed")
Any suggestion on how I can make this work??
I don't know Selenium, but it sounds like there may be multiple exceptions here, not all of the same type, and not where you might expect them to happen. For instance, everything is fine when row.is_displayed() evaluates to True, but an exception is thrown otherwise - This indicates to me that row might be None or some other unexpected result. I've taken a cursory look at the docs but I couldn't see right away.
Anyway - to debug this, try putting different sections of your code into try-except blocks:
try:
button = self.driver.find_element_by_xpath(PATH)
if button.is_displayed():
do stuff
try:
row = self.driver.find_element_by_xpath(<row6>)
except: # <-- Better if you test against a specific Exception!
print(" something is wrong with row! ")
try:
if row.is_displayed():
do stuff
else:
do stuff
except: # <-- Better if you test against a specific Exception!
print( " something is wrong with using row!" )
except: # <-- Better if you test against a specific Exception!
button = self.driver.find_element_by_xpath("PATH").is_displayed()
if button is False:
print("button is hidden. Test is passed")
Also, try to put a minimum amount of code inside each try-except, so that you know where the exception is coming from.
Maybe there's no hidden row6 to be found and an exception is raised.
The syntax of your except is wrong: as it is, it will catch all exceptions and then just do nothing with the NoSuchElementException object.
Did you mean:
except NoSuchElementException:
#do something when no row6 found
Related
I am writing a python / selenium script that trawls a website to find elements then ultimately write these element values to a table.
When it identifies that the element does not exist, it throws the NoSuchElementException as expected.
I have been trying to figure out how to override this exception, to instead, populate the table with a default value e.g. 'No Value'.
Problem is, python seems to ignore whatever I try, only to throw the exception regardless, resulting in the script execution ending prior to the table being able to be populated.
Any ideas?
file_1.py
def getAttributes(self):
...
...
...
try:
score = box.find_element(By.CLASS_NAME, 'dealClass').get_attribute('innerHTML').strip()
if not score:
raise NoSuchElementException(f"Score does not currently exist for {name}, as of {datetime.today()}")
except NoSuchElementException as e:
print('Exception is: ', e)
# Writing remediating code here but it never seems to work..
raise
...
file_2.py
def reportResults(self):
...
searchResults = self.find_element(By.ID, 'search_results_table')
report = ReportSearchResults)
table = PrettyTable(field_names=["Name", "Price", "Score"])
table.align["Name"] = "l"
table.align["Price"] = "l"
table.align["Score"] = "r"
table.add_rows(report.getAttributes())
print(table)
...
When you catch the exception, you can "fix" it by giving score a value. There's no need to reraise the exception at that point; you've handled it, so let your script proceed as if nothing happened.
def getAttributes(self):
...
try:
score = box.find_element(By.CLASS_NAME, 'dealClass').get_attribute('innerHTML').strip()
if not score:
# You're going to catch it, and you don't really need
# a long message telling you what went wrong. *You* raised
# this one, and you know why, and you're going to fix it.
raise NoSuchElementException("no score")
except NoSuchElementException as e:
score = 'No value'
...
I have the following code:
for button in buttons:
ActionChains(driver).move_to_element(button).perform()
time.sleep(2)
button.click()
time.sleep(2)
try:
wait_button.until(EC.presence_of_element_located((By.XPATH,'//div/h2')))
time.sleep(2)
name = driver.find_element_by_xpath('//div/h2').text
except:
wait_button.until(EC.presence_of_element_located((By.XPATH,'//span[#id="chat-header-title"]')))
time.sleep(2)
name = driver.find_element_by_xpath('//span[#id="chat-header-title"]').text
def pull_ul() -> list:
chat_frame = driver.find_element_by_xpath("//iframe[starts-with(#id, 'experience-container-')]")
driver.switch_to.frame(chat_frame)
wait_button.until(EC.presence_of_element_located((By.XPATH,'//ul[#aria-label="Chat content"]')))
the_ul =driver.find_element(By.XPATH,'//ul[#aria-label="Chat content"]')
new_lis =the_ul.find_elements(By.TAG_NAME,'li')
return new_lis
def pull_ul_again() -> list:
the_ul =driver.find_element(By.XPATH,'//ul[#aria-label="Chat content"]')
new_lis_2 =the_ul.find_elements(By.TAG_NAME,'li')
return new_lis_2
lis = pull_ul()
print(f"Archiving Chat with {name} ...\n")
print("this is len lis: ",len(lis), "for " + name)
And here is what the terminal shows:
As you can see, the code actually does run past the line that threw up the error, how is this possible? Also, why would this be happening , I successfully ran the code multiple times and suddenly it starts throwing the follwing error?
The loop that you're doing,
for button in buttons:
ActionChains(driver).move_to_element(button).perform()
...
is causing your StaleElementReferenceException because inside that you have driver.switch_to.frame(chat_frame), but you never switch back to default content or to the parent frame, which means that your buttons won't exist in that level, and so Selenium throws StaleElementReferenceException as a result. That could also happen if you navigate away from the page (which might also be happening depending on the button clicks).
If you ever switch frames or leave pages, you have to re-find elements in order to interact with them.
In python I have a function called func() which could raise NoSuchElementException:
I'm trying to call it with input1 if not correct call it with input2 else give up.
Is there any better way to write this code for clarity:
submit_button = None
try:
submit_button = func(input1)
except NoSuchElementException:
try:
submit_button = func(input2)
except NoSuchElementException:
pass
you can do something like:
for i in [input1, input2]:
try:
submit_button = func(i)
break
except NoSuchElementException:
print(f"Input {i} failed")
else:
print("None of the options worked")
If the first input doesn't throw an exception you break the loop, otherwise you keep in the loop and try the second input.
This way you can try as many inputs as you want, just add them into the list
The else at the end executes if you never broke the loop, which means none of the options worked
This works well if you want to try several inputs and treat them equally. For only two inputs your code looks readable enough to me. (try this, if it doesn't work try that)
Just another option...
from contextlib import suppress
submit_button = None
for i in input1, input2:
with suppress(NoSuchElementException):
submit_button = func(i)
break
Been on it two days now: Trying to automate sending a contact request to several people in a search result with a message. After login and search, iterating the add-buttons works and add_btn.click() opens the pop-ups. Only in the first instance, however, I successfully try: find_element_by_name to access the <textarea name="reason"> and can do element.send_keys()to insert my message. In the second iteration, I cannot seem to access the message form, although, when I print the iteration of driver.find_elements_by_xpath("//*[#name]"), <textarea name="reason"> is present.
I try to catch the most common exceptions but that does not seem to work.
Can anyone explain pls, 1) what is happening here and why the call for all named elements can list the textarea, but my specific call to find it does not work, and 2) how I could solve this problem. Thanks!
Here is the part of my code for going through search results:
def contact(text):
add_btns=driver.find_elements_by_css_selector("a.searchResult-actionLink.foundation-icon-core-contact-add.contact-lightbox-link")
i=0
wanted=6
for add_btn in add_btns:
i+=1
try:
add_btn.click()
time.sleep(2)
driver.save_screenshot("add%s.png" % (i,)) ###works on every turn!
elems=driver.find_elements_by_xpath("//*[#name]")
for elem in elems:
print i, elem.tag_name, elem.get_attribute("name") ###prints out 'textarea reason' on every turn!
try:
mssgbrd = driver.find_element_by_name("reason")
print "mssgbrd found" ###prints only on first round???
mssgbrd.send_keys(text)
driver.save_screenshot("request%s.png" % (i,))
except ElementNotVisibleException:
print "not visible"
except StaleElementReferenceException:
print "stale"
except NoSuchElementException:
print "no such element"
except TimeoutException:
print "timed out"
except:
print "something else happens"
request=driver.wait.until(EC.presence_of_element_located(
(By.CSS_SELECTOR,"#crl-button-send-request > a.element-form-button-solid-lime")))
try:
request.click()
time.sleep(3)
except TimeoutException:
print("Button not found!")
driver.save_screenshot("ButtonError%s.png" % (i,))
except:
print "Request not working" ###prints out on second round and after
driver.save_screenshot("xibit%s.png" % (i,)) ###get's called on second round and after
When I run this code, after the first successful iteration I keep getting the last exception "Request not working" for all other iterations. I have tested with close_button.click() closing the pop-up instead of sending the request - here the second iteration was successful.
I still can't assess, what the problem was, but this is how it got resolved. Maybe someone more experienced than me knows what happened.
In my original code I had a line with text=unicode(text.decode("utf-8")) just before
try:
mssgbrd = driver.find_element_by_name("reason")
print "mssgbrd found"
I cut it out for brevity in my post here, as I thought it would not be important. Boy, was I wrong... When experimenting, I added two instances of print time.ctime() to find out about a possible timeout or waiting period; one just between the utf-8-decoding and the try:-block, and one after the critical mssgbrd = driver.find_element_by_name("reason").
When running the code, on the second iteration none of them were printed, meaning that somehow the code stopped even before trying mssgbrd = driver.find_element_by_name("reason")just were the decoding took place. I then moved the decoding to the top of the function and was able to successfully send two invite messages. So basically, the function in my question should work fine, and if you were to add decoding the first lines would look like this:
def contact(text):
text=unicode(text.decode("utf-8"))
add_btns=driver.find_elements_by_css_selector("a.searchResult-actionLink.foundation-icon-core-contact-add.contact-lightbox-link")
i=0
wanted=6
for add_btn in add_btns:
i+=1
try:
add_btn.click()
time.sleep(2)
driver.save_screenshot("add%s.png" % (i,))
elems=driver.find_elements_by_xpath("//*[#name]")
for elem in elems:
print i, elem.tag_name, elem.get_attribute("name")
try:
mssgbrd = driver.find_element_by_name("reason")
print "mssgbrd found"
mssgbrd.send_keys(text)
driver.save_screenshot("request%s.png" % (i,))
except:
I would love to understand, however, what happened here.
am developing a python application . I have validated customer id from database. Means if the entered custid is present in database, i am raising an exception. In exception class i am printing the message . So far it is printing the message. But i am not sure how to get control back to the statement where i am taking the input.
main app
Custid=input("enter custid)
Validate_custid(Custid)
Print(Custid)
validate_custid module
From connections import cursor
From customExceptions import invalidcustidException
Def validate_custid(custid):
Cursor.execute("select count(custid) from customer where custid=:custid",{"custid":custid})
For row in cursor:
Count=row[0]
If Count==0:
Raise invalidcustidException
So far its printing the message in exception.now i want my program to take custid as input whenever this exception occurs. The process should iterate until user enters valid custid.
You should use a try-except block with else statement:
while True:
custid = input('Input custom Id: ')
try:
# Put your code that may be throw an exception here
validate_custid(custid)
except InvalidcustidException as err:
# Handle the exception here
print(err.strerror)
continue # start a new loop
else:
# The part of code that will execute when no exceptions thrown
print('Your custom id {} is valid.'.format(custid))
break # escape the while loop
Take a look at here: https://docs.python.org/3.4/tutorial/errors.html#handling-exceptions
You'll want a try except block.
try:
# portion of code that may throw exception
except invalidcuspidError:
# stuff you want to do when exception thrown
See https://docs.python.org/2/tutorial/errors.html for more.
What you are trying to do is called exception handling. I think the Python docs explain this better than me, so here you go: https://docs.python.org/2/tutorial/errors.html#handling-exceptions