Selenium tests fail after first test - python

I am trying to run selenium tests I've written for a Django project on a Debian server, using xvfb.
I have 3 tests I am trying to run, after the first test, they fail with this error:
NoSuchElementException: Message: u'Unable to locate element: {"method":"xpath","selector":"//a[#href=\\"#detail\\"]"}'
I have run export DISPLAY=:99 and am using Django LiveServerTestCase with django-selenium.
SELENIUM_DISPLAY = ':99' is set in my settings.py.
Here is my test runner:
class BaseLiveTest(LiveServerTestCase):
#classmethod
def setUpClass(cls):
cls.selenium = WebDriver()
super(BaseLiveTest, cls).setUpClass()
#classmethod
def tearDownClass(cls):
super(BaseLiveTest, cls).tearDownClass()
cls.selenium.quit()
def login(self, user):
#helper function, to log in users
#go to login page
self.selenium.get("%s%s" % (self.live_server_url, reverse('userena_signin')))
#wait for page to display
WebDriverWait(self.selenium, 10).until(
lambda x: self.selenium.find_element_by_id('id_identification'),
)
#fill in form and submit
identifictation_input = self.selenium.find_element_by_id('id_identification')
identifictation_input.send_keys(user.email)
password_input = self.selenium.find_element_by_id("id_password")
password_input.send_keys('password')
self.selenium.find_element_by_xpath('//form/descendant::button[#type="submit"]').click()
#wait for dashboard to load
WebDriverWait(self.selenium, 10).until(
lambda x: self.selenium.find_element_by_id('container'),
)
When I run each test by itself they all pass, but if I try to run them one after another the last 2 fail. Any ideas?

You need to use setUp() and tearDown(), not setUpClass() and tearDownClass(). The Class versions are run globally for the entire fixture, so all 3 tests are using the same WebDriver instance, and thus the browser isn't in the state you expect for your second and third tests.

Related

How do you clean up resources at the end of a pytest session?

I have a suite of selenium end to end tests. I instantiate one webdriver.ChromeDriver instance that I pass as a fixture to every test in the suite.
'''python3
#pytest.fixture(scope="session")
def driver(request):
return d(request)
'''
After the last test runs I want to close the webdriver instance with driver.quit().
I can accomplish this with a fixture
#pytest.hookimpl(trylast=True)
def close_after_test_suite(driver, requests):
if requests:
driver.quit()
However this only runs if tests do not fail during the suite. If every test passes, the browser will close. If a single test fails then the browser will be left open.
How can I use pytest to close my browser at the end of the test suite regardless of whether or not tests fail?
If you want to run some code on teardown, use yield instead of return, for example:
#pytest.fixture(scope="session")
def driver(request):
driver = d(request)
yield driver
driver.quit()
However, the selenium.webdriver.WebDriver classes implement the context manager magic methods, so you can also use the with statement:
#pytest.fixture(scope="session")
def driver(request):
with d(request) as driver:
yield driver
Another (although pretty old, but still working) option is using the request.addfinalizer option:
#pytest.fixture(scope="session")
def driver(request):
driver = d(request)
def f():
driver.quit()
request.addfinalizer(f)
return driver

Even after executing the code successfully pytest says empty suite and is not printing the print statements

I am trying to run one method from a different module in pytest using import. It runs correctly but in the report it says empty suite. Its not printing the print statements.
roboForm.py -
import unittest
from selenium import webdriver
from selenium.webdriver.support.select import Select
class Roboform(unittest.TestCase):
def setUp(self):
# create a new Chrome session
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(10)
self.driver.maximize_window()
self.driver.get("https://www.roboform.com/filling-tests")
def click_Custom_Form(self):
# get the xpath of the link and page
title = self.driver.title
assert title== "RoboForm Form Filling Tests"
print("We are on the right page")
#click on custom form link
self.custom_form = self.driver.find_element_by_xpath("//*[contains(text(),'Custom')]").click()
def close_browser(self):
self.driver.quit()
I am running the below code in pytest - test_classB.py
import self as self
from roboForm import Roboform
class Test():
Roboform.setUp(self)
print ("Browser and page launched from RoboForm")
self.driver.find_element_by_xpath("//*[contains(text(),'Custom')]").click()
print ("Test Passed")
Roboform.close_browser(self)
Getting the below error :
======================== no tests ran in 11.53 seconds ========================
Process finished with exit code 0
Empty suite
Empty suite
Agreed with #Corey Goldberg.
Try
def test_click_Custom_Form(self):
instead
def click_Custom_Form(self):

How to pass an url as argument through commandline to run selenium python test cases

Is there any proper way to using getting url in cmd as argument along testcases.py file?
I am running below commmand in cmd to run test cases of python file:
testcases.py "any url"
testcases.py have coding:
class JSAlertCheck(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome("E:\chromedriver.exe")
self.url = sys.argv[1]
def test_Case1(self):
driver = self.driver
def tearDown(self):
self.driver.quit()
if __name__ == "__main__":
unittest.main(sys.argv[1])
As per the discussion Python unittest passing arguments the Python Pundits seems to convey that:
Unit tests should be stand-alone which will have no dependencies outside of their setUp() and tearDown() methods. This is to make sure that each tests has minimal side-effects and reactions to the other test. Passing in a parameter defeats this property of unittest and thus makes them sort of invalid. Using a Test Configuration would have been the easiest way and more appropiate as a unittest should never rely on foreign data to perform the test.
If you still want to do so, here is one of the working solution:
Code Block:
from selenium import webdriver
import unittest
import sys
class MyTest(unittest.TestCase):
URL = "foo"
def setUp(self):
self.driver = webdriver.Chrome(executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
driver = self.driver
driver.get(self.URL)
def test_Case1(self):
driver = self.driver
print(driver.title)
def tearDown(self):
self.driver.quit()
if __name__ == "__main__":
if len(sys.argv) > 1:
MyTest.URL = sys.argv.pop()
unittest.main()
CLI Command:
python unittest_cmdline_urlASarguments.py http://www.python.org
Output:
C:\Users\AtechM_03\LearnAutmation\PythonProject\readthedocs>python unittest_cmdline_urlASarguments.py http://www.python.org
[4448:5632:0606/205445.017:ERROR:install_util.cc(589)] Unable to create registry key HKLM\SOFTWARE\Policies\Google\Chrome for reading result=2
DevTools listening on ws://127.0.0.1:5634/devtools/browser/40cc6c16-1e52-4f49-a54f-08fac3ff7abc
Welcome to Python.org
.
----------------------------------------------------------------------
Ran 1 test in 9.534s
OK
C:\Users\AtechM_03\LearnAutmation\PythonProject\readthedocs>
Commandline Snapshot:

Python-Selenium-Webdriver

I have a little issue with webdriver.My machine run windows 7 and successfuly install python and selenium webdriver.Here is the problem
When i run this file
from selenium import webdriver
import HTMLTestRunner
import unittest
class nexmo(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.get("http://wwww.facebook.com")
def test_login(self):
emailFieldId = "email"
el = self.driver.find_element_by_id(emailFieldId)
def tearDown(self):
self.driver.quit()
if __name__ == '__main__':
unittest.main()
The test give me
Ran 0
OK But the Firefox doesnt start and do the things i tell him.
When I run
from selenium import webdriver
self.driver = webdriver.Firefox()
self.driver.get("http://wwww.facebook.com")
emailFieldId = "email"
el = self.driver.find_element_by_id(emailFieldId)
self.driver.quit()
Everything is OK.The browser starts and find the element.
I took your code and copy/pasted it into my Eclipse and it ran fine.
By chance did you re-type this code into SO rather than copy paste? Is it possible that there is a typo in your "def test_login(self):" line such that unittest can't identify it as a test case? This is my best guess. Since unittest first checks to see if you have any unit tests (identified as a function with the pre-fix "test_". If and only if it finds a test case will it run setUp and tearDown.
Also, the point of unit testing is to actually test that you received a valid value. Can I recommend adding this to the end of "def test_login":
self.assertIsNotNone(el)

appium UI navigation issue python script

I'm new to python with android. I need to write python script.
basically what I want to do is when you click first view, I need to load second view. second view has button, when it press that I need to load third view.
class SimpleAndroidTests(unittest.TestCase):
def setUp(self):
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '4.2'
desired_caps['deviceName'] = 'Android Emulator'
desired_caps['app'] = PATH(
'mypath/aaa.apk'
)
desired_caps['appPackage'] = 'com.xxxx'
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
def test_find_elementsFirstview(self):
time.sleep(13)
textfields = self.driver.find_elements_by_class_name("android.widget.EditText")
textfields[0].send_keys("first text")
textfields[1].send_keys("second text")
el = self.driver.find_element_by_name("press Login")
el.click()
def test_secondView(self):
time.sleep(10)
textfields = self.driver.find_elements_by_class_name("android.widget.EditText")
textfields[2].send_keys("secondviewinput2")
def tearDown(self):
# end the session
self.driver.quit()
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(SimpleAndroidTests)
unittest.TextTestRunner(verbosity=2).run(suite)
ISSUE is it is not entering to the second view. It is re-loding first view again.
please help...
In your code you have a method - setUp(self) - which nose tools interprets as a "test setup" method, meaning it will be run before each test. Since your setUp() method instantiates the webdriver it is reloading your app before each test. Consider moving your driver instantiation to a setUpClass(), which nose tools will run before all tests in the file.
Example test file:
class YourTest(unittest.TestCase):
#classmethod
def setUpClass(cls):
[...runs before all tests...]
def setUp(self):
[...runs before each test...]
def test_test1(self):
[...your tests...]
def tearDown(self):
[...runs after each test...]
#classmethod
def tearDownClass(cls):
[...runs after all tests...]
When an element on an android app is clicked via appium python script, then appium has no control over the expected behavior. It is the app that handles the click. So for example, if there is a Login button and if you do this:
el = self.driver.find_element_by_name("press Login")
el.click()
This click on the element is handled by the app and app will take over the flow from here. It is app that launches the next screen. For example, it could be a form.
Basically, appium python client has control over which UI element to choose, but what that particular UI element will do is up to the app.

Categories