I am trying to check if an element exists on an HTML page with Selenium/Python.
This is my function:
class runSelenium(object):
def __init__(self):
# define a class attribute
self.driver = webdriver.Firefox()
def isElementPresent(self, locator):
try:
self.driver.find_element_by_xpath(locator)
except NoSuchElementException:
print ('No such thing')
return False
return True
def selenium(self):
self.driver.get("https://somepage.com")
isElement = self.isElementPresent("//li[#class='item'][6]")
isElement1 = str(isElement)
if __name__ == '__main__':
run = runSelenium()
run.selenium()
I am trying to pick the result with a Boolean value but with no luck:
isElement = self.isElementPresent("//li[#class='item'][6]")
What am I missing here?
You need to un-indent the last code block:
class runSelenium(object):
def __init__(self):
# define a class attribute
self.driver = webdriver.Firefox()
def isElementPresent(self, locator):
try:
self.driver.find_element_by_xpath(locator)
except NoSuchElementException:
print ('No such thing')
return False
return True
def selenium(self):
self.driver.get("https://somepage.com")
isElement = self.isElementPresent("//li[#class='item'][6]")
isElement1 = str(isElement)
if __name__ == '__main__':
run = runSelenium()
run.selenium()
So I restarted the IDE (Visual Studio 2013) and it works now fine.. The code is correct 100%
Related
Appium automation runs and ends correctly inside one class, but fails when another class is created.
I tried to to delete all attributes in init, except first one and it helps.
Main Class(works well)
import unittest
from appium import webdriver
from ScreenObjects.SendMessage import SendMsg
class AppTestAppium(unittest.TestCase):
def setUp(self):
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = ''
desired_caps['deviceName'] = '81e9b20e'
desired_caps['appPackage'] = 'org.telegram.messenger'
desired_caps['appActivity'] = 'org.telegram.ui.LaunchActivity'
desired_caps['noReset'] = 'True'
self.driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub',desired_caps)
def tearDown(self):
"Tear down the test"
self.driver.quit()
def test_send_messge_to_olga(self):
"Test is sending message"
contactItem = self.driver.find_element_by_xpath("//android.view.ViewGroup[contains(#index,'2')]")
contactItem.click()
elementTypeField = self.driver.find_element_by_xpath("//android.widget.EditText[contains(#index,'1')]")
elementTypeField.clear()
elementTypeField.send_keys("Hello. If you are reading this, my first appium automation has passed")
sendButton = self.driver.find_element_by_xpath("//android.widget.ImageView[#content-desc ='Send']")
sendButton.click()
if __name__ == '__main__':
unittest.main()
Main class(fails)
import unittest
from appium import webdriver
from ScreenObjects.SendMessage import SendMsg
class AppTestAppium(unittest.TestCase):
def setUp(self):
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = ''
desired_caps['deviceName'] = '81e9b20e'
desired_caps['appPackage'] = 'org.telegram.messenger'
desired_caps['appActivity'] = 'org.telegram.ui.LaunchActivity'
desired_caps['noReset'] = 'True'
self.driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub',desired_caps)
def tearDown(self):
"Tear down the test"
self.driver.quit()
def test_send_messge_to_olga(self):
"Test is sending message"
send_message = SendMsg(self.driver)
send_message.chooseContact()
send_message.typeMsg()
send_message.clickSend()
if __name__ == '__main__':
unittest.main()
with one more Class (fails)
class SendMsg(object):
def __init__(self, driver):
self.contactItem = driver.find_element_by_xpath("//android.view.ViewGroup[contains(#index,'2')]")
self.elementTypeField = driver.find_element_by_xpath("//android.widget.EditText[contains(#index,'1')]")
self.sendButton = driver.find_element_by_xpath("//android.widget.ImageView[#content-desc ='Send']")
def chooseContact(self):
self.contactItem.click()
def typeMsg(self):
self.elementTypeField.clear()
self.elementTypeField.send_keys("Hello")
def clickSend(self):
self.sendButton.click()
I expect TEST PASSED, but the actual output is 'An element could not be located on the page using the given search parameters.'
I have started using Python Selenium and wrote a script shown below.
This prints a return code linked to the test that fails (test01, test02, test03, ..).
Ignore that each test is checking the same thing.
I'm just trying to understand if there's a cleaner way to write the tests because each one repetitively declares global res, and then has a try/except block.
Could anyone offer some advice on how to improve this please?
# global variable for return code. Zero is success.
res=0
#atexit.register
def send_health():
print ("res=%s") % res
class Login(unittest2.TestCase):
#classmethod
def setUpClass(inst):
binary = FirefoxBinary('C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe')
inst.driver = webdriver.Firefox(firefox_binary=binary)
inst.base_url = "https://stackoverflow.com"
def test01(self):
global res
driver = self.driver
try:
self.assertEqual("Ask a Question", driver.title)
except Exception,e:
print ("Exception: %s" % e)
driver.save_screenshot('screenshot_test01.png')
res=1
return
def test02(self):
global res
driver = self.driver
try:
self.assertEqual("Ask a Question", driver.title)
except Exception,e:
print ("Exception: %s" % e)
driver.save_screenshot('screenshot_test02.png')
res=2
return
def test03(self):
global res
driver = self.driver
try:
self.assertEqual("Ask a Question", driver.title)
except Exception,e:
print ("Exception: %s" % e)
driver.save_screenshot('screenshot_test03.png')
res=3
return
if __name__ == "__main__":
unittest2.main()
There is no need for global variables here at all. You are inside a class; use self.res throughout.
That's exactly what setUp instance method is for, quite similar to setUpClass method that is run once per test class.
def setUp(self):
# this code will be executed before each and every test
self.res = 0
def tearDown(self):
# this code will be executed post each and every test.
By the way, why are you using global variables? There's no need for them. In fact, there's seldom a valid rationale for using globals. Moreover, tests need to be isolated and independent, using global variables would violate that rule.
Thanks for the tips above. I've reduced the code down to this version which hopefully looks cleaner and more standard:
class Login(unittest2.TestCase):
#classmethod
def handleError(self, e, res):
print ("Test failed with exception: %s" % e)
self.result = res
sys.exit()
#classmethod
def setUpClass(self):
binary = FirefoxBinary('C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe')
self.driver = webdriver.Firefox(firefox_binary=binary)
self.base_url = "https://stackoverflow.com"
self.result = 0
def test01(self):
driver = self.driver
try:
self.assertEqual("Ask a Question", driver.title)
except Exception,e:
self.handleError(e, 1)
def test02(self):
driver = self.driver
try:
self.assertEqual("Ask a Question", driver.title)
except Exception,e:
self.handleError(e, 2)
def test03(self):
driver = self.driver
try:
self.assertEqual("Ask a Question", driver.title)
except Exception,e:
self.handleError(e, 3)
#classmethod
def tearDownClass(self):
self.driver.quit()
print ("res=%s") % self.result
if __name__ == "__main__":
unittest2.main()
I'm trying to write a test in Selenium using python,
I managed to run the test and it passed, But now I want add arg parser so I can give the test a different URL as an argument.
The thing is that my test is inside a class,
So when I'm passing the argument I get an error:
app_url= (args['base_url'])
NameError: global name 'args' is not defined
How can I get args to be defined inside the Selenium class?
This is my code:
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
from selenium import webdriver
import unittest, time, re
import os
import string
import random
import argparse
def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(8))
agmuser = id_generator()
class Selenium(unittest.TestCase):
def setUp(self):
chromedriver = "c:\chromedriver.exe"
os.environ["webdriver.chrome.driver"] = chromedriver
self.driver = webdriver.Chrome(chromedriver)
app_url = (args['base_url'])
#app_url= "http://myd-vm16635.fufu.net:8080/"
print "this is the APP URL:" + ' ' + app_url
self.base_url = app_url
self.verificationErrors = []
self.accept_next_alert = True
def test_selenium(self):
#id_generator.user = id_generator()
driver = self.driver
driver.get(self.base_url + "portal/")
driver.find_element_by_css_selector("span").click()
driver.find_element_by_id("j_loginName").clear()
driver.find_element_by_id("j_loginName").send_keys(agmuser)
driver.find_element_by_id("btnSubmit").click()
driver.find_element_by_link_text("Login as" + ' ' + agmuser).click()
driver.find_element_by_css_selector("#mock-portal-Horizon > span").click()
# driver.find_element_by_id("gwt-debug-new-features-cancel-button").click()
# driver.find_element_by_xpath("//table[#id='gwt-debug-module-dropdown']/tbody/tr[2]/td[2]").click()
# driver.find_element_by_id("gwt-debug-menu-item-release-management").click()
def is_element_present(self, how, what):
try: self.driver.find_element(by=how, value=what)
except NoSuchElementException as e: return False
return True
def is_alert_present(self):
try: self.driver.switch_to_alert()
except NoAlertPresentException as e: return False
return True
def close_alert_and_get_its_text(self):
try:
alert = self.driver.switch_to_alert()
alert_text = alert.text
if self.accept_next_alert:
alert.accept()
else:
alert.dismiss()
return alert_text
finally: self.accept_next_alert = True
def tearDown(self):
self.driver.quit()
self.assertEqual([], self.verificationErrors)
if __name__ == "__main__":
#####################******SCRIPT PARAMS****;**###################################
# these values can be changed type 'python selenium_job.py --help' for assistance
##################################################################################
parser = argparse.ArgumentParser(description='DevOps team - Sanity test')
parser.add_argument('-b', '--base_url', help='base_url', default="http://myd-vm16635.fufu.net:8080/")
args = vars(parser.parse_args())
unittest.main()
Put the parser = argparse.ArgumentParser(...) and parser.add_argument() outside if __name__ == "__main__": so that it always gets created but not evaluated. Keep args = vars(parser.parse_args()) inside __main__.
That way you can import it from the file like from selenium_tests import parser and then in your other script, do parser.parse_args().
And a cleaner way to do it is to create a function which returns the parser, like:
def get_parsed_args():
parser = argparse.ArgumentParser(...)
parser.add_argument(...)
# etc.
args = parser.parse_args()
return args
# or just...
return parser.parse_args()
#and then call that in the main program:
if __name__ == '__main__':
args = get_parsed_args()
# etc.
And in other scripts which you want to import it into, do
from selenium_tests import get_parsed_args
if __name__ == '__main__':
args = get_parsed_args()
# etc.
I'm having some real issues trying to work out how to get this to work, and I'm sure there are some experts on here who can work it out for me, please :)
So I have a number of test cases in python that all follow on from each other, but are individual scripts, I want to combine these and run them in order, in a single webdriver instance, as they all follow on, but I can't seem to work out how to do it..
I have created a test suite -
import unittest
from Searchfieldreturnscorrectvalue import SearchFieldReturnsCorrectValue
from Navigatetostreetlightprecontentpage import Navigatetostreetlightprecontentpage
class TestSuite(unittest.TestSuite):
def suite():
suite = unittest.TestSuite()
suite.addTest(Searchfieldreturnscorrectvalue('test_searchfieldreturnscorrectvalue'))
suite.addTest(Navigatetostreetlightprecontentpage('test_navigatetostreetlightprecontentpage'))
return suite
if __name__ == "__main__":
unittest.main()
This runs the tests, but the second one fails as it tried to run it in a second firefox instance..
Searchfieldreturnscorrectvalue.py
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest, time, re
class SearchFieldReturnsCorrectValue(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
self.base_url = "https://www.XXXXX.com/"
self.verificationErrors = []
self.accept_next_alert = True
def test_search_field_returns_correct_value(self):
driver = self.driver
driver.get(self.base_url + "/")
driver.find_element_by_id("edit-search-block-form--2").click()
driver.find_element_by_id("edit-query").clear()
driver.find_element_by_id("edit-query").send_keys("street light")
driver.find_element_by_id("edit-query").send_keys(Keys.ENTER)
for i in range(60):
try:
if self.is_element_present(By.LINK_TEXT, "Street lighting"): break
except: pass
time.sleep(1)
else: self.fail("time out")
try: self.assertEqual("Street lighting", driver.find_element_by_link_text("Street lighting").text)
except AssertionError as e: self.verificationErrors.append(str(e))
def is_element_present(self, how, what):
try: self.driver.find_element(by=how, value=what)
except NoSuchElementException as e: return False
return True
def is_alert_present(self):
try: self.driver.switch_to_alert()
except NoAlertPresentException as e: return False
return True
def close_alert_and_get_its_text(self):
try:
alert = self.driver.switch_to_alert()
alert_text = alert.text
if self.accept_next_alert:
alert.accept()
else:
alert.dismiss()
return alert_text
finally: self.accept_next_alert = True
def tearDown(self):
self.assertEqual([], self.verificationErrors)
if __name__ == "__main__":
unittest.main()
Navigatetostreetlightprecontentpage.py
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest, time, re
class Navigatetostreetlightprecontentpage(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.verificationErrors = []
self.accept_next_alert = True
def test_navigatetostreetlightprecontentpage(self):
driver = self.driver
driver.find_element_by_link_text("Street lighting").click()
try: self.assertEqual("Street lighting", driver.find_element_by_css_selector("h1.page-title__main__title").text)
except AssertionError as e: self.verificationErrors.append(str(e))
try: self.assertEqual("Report a faulty street light | Cheshire East", driver.title)
except AssertionError as e: self.verificationErrors.append(str(e))
def is_element_present(self, how, what):
try: self.driver.find_element(by=how, value=what)
except NoSuchElementException as e: return False
return True
def is_alert_present(self):
try: self.driver.switch_to_alert()
except NoAlertPresentException as e: return False
return True
def close_alert_and_get_its_text(self):
try:
alert = self.driver.switch_to_alert()
alert_text = alert.text
if self.accept_next_alert:
alert.accept()
else:
alert.dismiss()
return alert_text
finally: self.accept_next_alert = True
def tearDown(self):
self.assertEqual([], self.verificationErrors)
if __name__ == "__main__":
unittest.main()
I don't know if a test suite is the correct way to do it, or to just get all the tests into one file, but I still would want the "Classes/Tests" to individually report pass/fail, at the moment I can't get that to work, I think it is something to do with the setUp(self) needing to be moved to a setUpModule and shared? But I can't work it out, if someone could please point me in the right direction, I would be very grateful.
Thanks
Update
Example of what I have tired as per comment bellow, still not working..
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import unittest, time, re
class SeleniumTest(unittest.TestCase):
#classmethod
def setUpClass(cls):
cls.driver = webdriver.Firefox()
cls.driver.maximize_window()
#classmethod
def tearDownClass(cls):
cls.driver.close()
cls.driver.quit()
class SearchFieldReturnsCorrectValue(SeleniumTest):
def setUp(cls):
cls.base_url = "https://www.XXXXX.com"
cls.verificationErrors = []
cls.accept_next_alert = True
def test_search_field_returns_correct_value(cls):
driver = cls.driver
driver.get(cls.base_url + "/")
driver.find_element_by_id("edit-search-block-form--2").click()
driver.find_element_by_id("edit-query").clear()
driver.find_element_by_id("edit-query").send_keys("street light")
driver.find_element_by_id("edit-query").send_keys(Keys.ENTER)
for i in range(60):
try:
if cls.is_element_present(By.LINK_TEXT, "Street lighting"): break
except: pass
time.sleep(1)
else: cls.fail("time out")
try: cls.assertEqual("Street lighting", driver.find_element_by_link_text("Street lighting").text)
except AssertionError as e: cls.verificationErrors.append(str(e))
driver.find_element_by_link_text("Street lighting").click()
def is_element_present(cls, how, what):
try: cls.driver.find_element(by=how, value=what)
except NoSuchElementException as e: return False
return True
def is_alert_present(cls):
try: cls.driver.switch_to_alert()
except NoAlertPresentException as e: return False
return True
def close_alert_and_get_its_text(cls):
try:
alert = cls.driver.switch_to_alert()
alert_text = alert.text
if cls.accept_next_alert:
alert.accept()
else:
alert.dismiss()
return alert_text
finally: cls.accept_next_alert = True
def tearDown(cls):
cls.assertEqual([], cls.verificationErrors)
class Navigatetostreetlightprecontentpage(SeleniumTest):
def setUp(cls):
cls.verificationErrors = []
cls.accept_next_alert = True
def test_navigatetostreetlightprecontentpage(cls):
driver = cls.driver
try: cls.assertEqual("Street lighting", driver.find_element_by_css_selector("h1.page-title__main__title").text)
except AssertionError as e: cls.verificationErrors.append(str(e))
try: cls.assertEqual("Report a faulty street light | Cheshire East", driver.title)
except AssertionError as e: cls.verificationErrors.append(str(e))
def is_element_present(cls, how, what):
try: cls.driver.find_element(by=how, value=what)
except NoSuchElementException as e: return False
return True
def is_alert_present(cls):
try: cls.driver.switch_to_alert()
except NoAlertPresentException as e: return False
return True
def close_alert_and_get_its_text(cls):
try:
alert = cls.driver.switch_to_alert()
alert_text = alert.text
if cls.accept_next_alert:
alert.accept()
else:
alert.dismiss()
return alert_text
finally: cls.accept_next_alert = True
def tearDown(cls):
cls.assertEqual([], cls.verificationErrors)
if __name__ == "__main__":
unittest.main()
This seems to be running both classes now, but the second class is never able to locate any elements, but the same line in the first class works perfectly.
I am not sure I understood well, but to use a single driver instance, you can use the setupClass class method where you create the driver:
class MyTestClass(unittest.TestCase):
#classmethod
def setUpClass(cls):
cls.driver = webdriver.Firefox()
#classmethod
def tearDownClass(cls):
cls.driver.close()
cls.driver.quit()
def setUp(self):
....
It will still recreate the driver for every new test class, but it does not recreate one for every test (as setUp does).
Personnally I make all my test classes inherit from a SeleniumTest class like this:
class SeleniumTest(unittest.TestCase):
#classmethod
def setUpClass(cls):
cls.driver = webdriver.Firefox()
#classmethod
def tearDownClass(cls):
cls.driver.close()
cls.driver.quit()
class MyTestClass(SeleniumTest):
def setUp(self):
....
import unittest
from selenium import webdriver
from time import sleep
class SeleniumTest(unittest.TestCase):
global driver
#classmethod
def setUpClass(cls):
#getting a common webdriver instance for all your tests for this module
cls.driver = webdriver.Chrome("/Users/sibasish/PycharmProjects/CommonDriverInstance/chromedriver")
cls.driver.get("https://www.google.com")
#classmethod
def tearDownClass(cls):
cls.driver.close()
cls.driver.quit()
class MyTestClass(SeleniumTest):
def setUp(self):
pass
def test_sample1(self):
print("hello1")
self.driver.get("https://www.google.com/")
sleep(4)
def test_sample2(self):
print("hello2")
self.driver.get("https://www.facebook.com/")
sleep(4)
I'm trying to create a class that can create wedriver instances and add proxies to them, this is only a dumbed down version of what i've already written, but I'm also trying to make a method that will wait for an element to be visible before clicking it, the attribute is isn't getting passed to the driver object.
Edit: The code as it was, was hard to understand out of context so I added the whole class as I'm working on it. I've also changed the click_elem method to a static method but now it just times out even though the element is visible.
class Driver:
proxies = []
#staticmethod
def test_proxy(proxy):
try:
urllib.urlopen(
"https://www.google.com",
proxies={'http': proxy})
return True
except IOError:
print "Connection error! (Check proxy)"
return False
else:
return False
def get_proxied_driver(self):
for proxy in self.proxies:
try:
myproxy = self.proxies.pop()
if self.test_proxy(myproxy):
proxy = Proxy({
'proxyType': ProxyType.MANUAL,
'httpProxy': myproxy,
'ftpProxy': myproxy,
'sslProxy': myproxy,
'noProxy': '' # set this value as desired
})
driver = webdriver.Firefox(proxy=proxy)###### chrome, phantom js & IE etc ##
is_working = raw_input('Is your proxy working? [y/n]: ') # use selenium assert
if is_working == 'y' or is_working == 'Y':
return driver
if is_working == 'n' or is_working == 'N':
driver.quit()
continue
if not is_working == 'y' or is_working == 'Y' or is_working == 'n' or is_working == 'N':
print 'Invallid'
except:
continue
# needs working_proxies.txt in the same dir
def get_proxies(self):
with open('working_proxies.txt', 'rb') as working_proxies:
for proxy in working_proxies:
proxy.rstrip()
self.proxies.append(proxy.decode('ascii'))
def get_proxies_n_driver(self): # same as get_driver but it adds proxies from -
self.get_proxies() # working_proxies.txt to proxies list
driver = self.get_proxied_driver()
return driver
#staticmethod
def click_elem(driver, elem_type, elem):
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((elem_type, elem)))
if elem_type == By.CLASS_NAME:
find = find_element_by_class_name
elem = driver.find(elem).click()
driver = Driver()
#driver.test_proxy('213.136.79.124:80')
new_driver = driver.get_proxies_n_driver()
new_driver.get("https://twitter.com/signup")
driver.click_elem(new_driver, By.CLASS_NAME, "submit_button")
I've also got another Script that tests the proxies and then adds them to working_proxies.txt