Writing tests with selenium and unittest Python - python

I am writing a simple sign in test using unittest and selenium.
I would like to know how does Unittest know if a test has failed or not? I want to print "Pass" in my terminal if the sign in was successful and "Fail" if there was an error, like incorrect password.
This is what I have at the moment.
class SignIn(unittest.TestCase):
def setUp(self):
self.driver = driver
self.driver.get('https://example')
def test_sign_in(self):
self.driver.find_element_by_name('user[email]').send_keys('example')
self.driver.find_element_by_name('user[password]').send_keys('example')
self.driver.find_element_by_name('commit').click()
def tearDown(self):
self.driver.close()
if __name__ == '__main__':
unittest.main()

You can user Asserts,
Let's say once you are logged in, you will either see dashboard or welcome screen, right ?
You need to assert them like below :
try:
assert "Expected_message_here" in driver.find_element_by_xpath('welcome page xpath here').text
except:
print("looks like a failure")
pass
This links contains all the asserts click here
and I would suggest you to have a different function to validate fail scenarios.
you can refer here also

Method 1:
If there's any successful sign-in message once the user is logged in, you can use a simple if-else statement. You may use the below patch of code
def test_sign_in(self):
self.driver.find_element_by_name('user[email]').send_keys('example')
self.driver.find_element_by_name('user[password]').send_keys('example')
self.driver.find_element_by_name('commit').click()
success_msg=find_element_by_xpath('{{xpath of the success message}}')
WebDriverWait(driver, 5).until(EC.element_to_be_clickable(By.XPATH,success_msg))
if success_msg:
print("Successfully logged in")
else:
print("Unsuccessful")
Method 2:
You may use a Try Except block.
def test_sign_in(self):
try:
self.driver.find_element_by_name('user[email]').send_keys('example')
self.driver.find_element_by_name('user[password]').send_keys('example')
self.driver.find_element_by_name('commit').click()
print("Successfully logged in")
except:
print("An exception occurred")
The above samples are raw code. Correct the identation, typos etc. Try it out and let me know if it worked for you! Cheers.

Related

Locust/Python: Splitting a tasks array with if conditions in a SequentialTaskSet

I'm new to Locust, and Python in general. I've been using JMeter for several years, and I'm trying to implement similar logic to what I've used there for handling failures in login.
I want to run a simple scenario: Login, Enter a folder, Logout
Where I'm having trouble is implementing this logic:
If any login call fails, I don't want to attempt the folder enter (avoid a cascading failure after login), but I still want to run the logout to ensure there is no active session.
My current SequentialTaskSet reads like this, which works for executing the child tasksets:
class folder_enter_scalability_taskset(SequentialTaskSet):
def on_start(self):
self.tm = TransactionManager()
#task
def seedata_config(self):
seeddata = next(seeddata_reader)
self.client.username = seeddata['username']
self.client.password = seeddata['password']
tasks = [login_taskset, folder_enter_taskset, logout_taskset]
Is there a way to split up the tasks array into multiple steps within the same SequentialTaskSet?
Always Login
if login passed, enter folder
Always Logout
Thanks to phil in the comments for pointing me in the right direction, I now have a working code with try-finally and if-else instead of a tasks array. Hope this can help someone else:
class folder_enter_scalability_taskset(SequentialTaskSet):
def on_start(self):
self.tm = TransactionManager()
#task
def seedata_config(self):
seeddata = next(seeddata_reader)
self.client.username = seeddata['username']
self.client.password = seeddata['password']
self.client.userrole = seeddata['userrole']
#task
def folder_enter_scalability(self):
try:
login_taskset.login(self)
if self.client.loginFail is False:
folder_enter_taskset.folder_enter(self)
else:
logging.error("Login failed, skipping to logout")
finally:
logout_taskset.logout(self)
I wasn't having luck with getting it to skip folder enter if I placed it in a try-else-finally condition, so I went with adding this self.client.loginFail in the login taskset to support if-else within try.
It's initiated as 'False', and flipped to 'True' in case of failure in the taskset.

Running a function based on user input

I would like to enter the word login into the console and have my function run. (I am fairly new to Python so if I don't understand some of the scripts you are sending bear with me.)
I expect the output to be Login successful.
The function I want to run is the following (or Log_in):
def log_in():
print("Username:"); print('Batman_20082')
print("Password:"); print('*******')
print("Logging in! Please Wait")
log_in();
Second Question
Hello!
I am working on a python login logout feature! I want to cancel the logout feature if the login feature hasn't been used.
def log_in():
print("Username:"); print('Batman_20082')
print("Password:"); print('*******')
print("Logging in! Please Wait")
if(input() == 'login'):
log_in()
def log_out():
print("Successfully logged out!")
if(input() == 'logout'):
log_out()
Code Above!
Thanks to GLHR for the help with the if input code!
I would highly appreciate if you help me get to 15 rep! So i can plus rep the people that help me!
I want to be the output to be, you haven't logged in yet. or something like that.
Use the input() method to get user input and compare it to the command login. If they match, run your function:
def log_in():
print("Username:"); print('Batman_20082')
print("Password:"); print('*******')
print("Logging in! Please Wait")
if input() == 'login':
log_in()
input() will wait till the user presses Enter.
If you want to keep asking for the command until a valid command is answered (instead of quitting after the first command), you can use a while loop instead:
while input() != 'login':
print("Invalid command, try again")
log_in()

Selenium webdriver isn't able to clear a field, but is able to send_keys to it

I'm trying to create a program that signs up for instagram with a new account, I've got the emails and the rest generated, when I go ahead and send_keys to the appropriate fields, it does it just fine. I wanted to implement a retry function, which would clear the email field and try with a different mail. However this does not work, even though send_keys to it worked previously? Snippet of my code below.
driver.get('https://www.instagram.com')
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(mail)
driver.find_element_by_xpath("//*[contains(#aria-label,'Full')]").send_keys(name + lastname)
driver.find_element_by_xpath("//*[contains(#aria-label,'User')]").send_keys(namae+lastonamae+pamae2)
driver.find_element_by_xpath("//*[contains(#aria-label,'Password')]").send_keys(password)
driver.find_element_by_xpath("//*[contains(#type,'submit')]").click()
This attempts to create a new account with the appropriate credentials, however when it fails, I want it to try to look for an element that is only present when it fails, and if it finds that, it should clear the email field and retry with a different one. Code below.
driver.find_element_by_xpath('//*[#id="react-root"]/section/main/article/div[2]/div[1]/div/form/div[3]/div/div[2]/span') #this looks for the element only present on the fail page
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").clear()
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(mail2)
It doesn't clear the field, but doesn't raise an error either. It then proceeds to type the 2nd email with no problems. I appreciate any help on the matter.
EDIT: Posting a bigger chunk of the code.
def signup():
driver.get('https://www.instagram.com')
time.sleep(7)
if trycounter < 3: #this is almost always true, just a failsafe
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(mail1)
driver.find_element_by_xpath("//*[contains(#aria-label,'Full')]").send_keys(name + ' ' + lastname)
driver.find_element_by_xpath("//*[contains(#aria-label,'User')]").send_keys(name+lastname+extension)
driver.find_element_by_xpath("//*[contains(#aria-label,'Password')]").send_keys(password)
driver.find_element_by_xpath("//*[contains(#type,'submit')]").click()
time.sleep(7)
try: #this only executes if a popup that wants you to confirm your age pops up
driver.find_element_by_xpath('//*[#id="igCoreRadioButtonageRadioabove_18"]').click()
driver.find_element_by_xpath('/html/body/div[3]/div/div[3]/div/button').click()
time.sleep(5)
except:
pass
try:
randomgen() #generates the mail,password and name
driver.find_element_by_xpath('//*[#id="react-root"]/section/main/article/div[2]/div[1]/div/form/div[3]/div/div[2]/span')
time.sleep(1)
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").clear()
time.sleep(1)
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(mail2)
driver.find_element_by_xpath("//*[contains(#aria-label,'User')]").send_keys(username)
driver.find_element_by_xpath("//*[contains(#type,'submit')]").click()
time.sleep(7)
You can use following code as alternative for clear method:
from selenium.webdriver.common.keys import Keys
email_element = driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]")
email_element.send_keys(Keys.CONTROL, 'a')
email_element.send_keys(mail1)
fullname_element = driver.find_element_by_xpath("//*[contains(#aria-label,'Full')]")
fullname_element.send_keys(Keys.CONTROL, 'a')
fullname_element.send_keys(name + ' ' + lastname)
# do it for other field as well
So this will definitely work as a workaround. I just tried it on instagram. Although there was no field with an aria label called Email for me. It was aria-label "Mobile Number or Email" for me.
driver.execute_script("$(\"input[aria-label='Email']"\").value = '';");
I will keep looking at it to see why the clear command didn't work though.
You can try something like this to delete mail1.
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(Keys.chord(Keys.CONTROL,"a"))
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(Keys.DELETE)
driver.find_element_by_xpath("//*[contains(#aria-label,'Email')]").send_keys(mail2)

Python IF statement can't recognize else:

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

How to test Login error validation python selenium

I need to test Login page validation. If the user doesn't enter username, then the formErrorContent need to show beside the username.
This is what I did
def test_UserNameValidate(self):
self.driver.getElement("id", "user").click()
self.driver.getElement("id", "password").click()
user = self.driver.getElement("id", "user")
try:
error_user = user.find_element_by_xpath('//*[#id="login-usr"]/div/div[#class="formErrorContent"]')
except NoSuchElementException:
error_user = None
This test is passing. I got the try and except method from web and changed for my condition. I'm not sure I'm doing right validation. Also, I didn't understand whats going on Try and except. Can someone help to solve this puzzle?
Thanks
If you don't use try except your script will fail in case of no error message disappear (try except 'ignore' NoSuchElementException). You should also write assertion to check if message is present, because if you use try except the test will always pass.

Categories

Resources