Reputation: 85
I have an application with six functions. Each of them begins with logging in to the website. I create another class named login (below the code). The structure of the project is 6 classes and main class. How do you use this function in these six classes? This my code for login in every single class and login class
class ClassName1(unittest.TestCase):
WebDriver driver=new FirefoxDriver();
driver.get("URL");
login=driver.find_element_by_name('Login')
password=driver.find_element_by_name('Password')
username.send_keys("login")
password.send_keys("password")
driver.find_element_by_name("submit").click()
I created Login class:
class Login(unittest.TestCase)
def log(self):
WebDriver driver=new FirefoxDriver();
driver.get("URL");
login=driver.find_element_by_name('Login')
password=driver.find_element_by_name('Password')
username.send_keys("login")
password.send_keys("password")
selenium.find_element_by_name("submit").click()
My proposition is:
from file import Login -> to ClassName1 and in class: Login.log() but I don't know how use this I have two session browser and error i don't know how to combine it into one session
And second question in my app in every single class I make - webdriver, can I test my six class in on browser session? Every single class open browser. I would like this in one. It's possible ? And second question in my app in every single class I make - webdriver, can I test my six class in one browser session? It's possible ? How I should change my code? Thank you!
Upvotes: 0
Views: 1624
Reputation: 5139
Your issue isn’t about Selenium; your issue is about sharing test data across tests. (The test data just happens to be a Selenium driver.)
With unittest
, setup can be done in one of two ways.
If you add a setUp()
instance method to your test case, unittest
will call it before each test. (Similarly, if you add a tearDown()
instance method to your test case, unittest
will call it after each test.)
Because it is an instance method, you have access to the test instance (i.e., self
). Data that is set up in this method can be assigned to various properties on the instance for later use in the actual test functions.
You could use this function to set up your driver before each test (and tear it down after):
class MyTestCase(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.driver.get("http://www.example.com")
self.driver.find_element_by_link_text("Log in").click()
# ...
def tearDown(self):
self.driver.quit()
def test_creating_a_widget(self):
self.driver.find_element_by_link_text("New widget").click()
# ...
def test_creating_a_whatsit(self):
self.driver.find_element_by_link_text("New whatsit").click()
# ...
Importantly, this will still create a new driver (session) for each test. But...
If you add a setUpClass()
class method to your test case, unittest
will call it once (and only once) before all tests in the test case are run. (Similarly, if you add a tearDownClass()
class method to your test case, unittest
will call it once (and only once) after all tests in the test case are run.)
Because it is a class method, you have access to the test class (i.e., cls
). Data that is set up in this method can be assigned to various properties on the class for later use in the actual test functions.
class MyTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.driver = webdriver.Firefox()
@classmethod
def tearDownClass(cls):
cls.driver.quit()
If you share the driver across tests, each test will pick up where the previous test left off. In other words, your tests won't be isolated, which can make writing and debugging your tests much, much more difficult.
To address this, we need to reset between each test. For that, we can go back to the setUp()
and tearDown()
instance methods:
class MyTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.driver = webdriver.Firefox()
def setUp(self):
self.driver.get("http://www.example.com")
self.driver.find_element_by_link_text("Log in").click()
# ...
def tearDown(self):
self.driver.get("about:blank")
@classmethod
def tearDownClass(cls):
cls.driver.quit()
def test_creating_a_widget(self):
self.driver.find_element_by_link_text("New widget").click()
# ...
def test_creating_a_whatsit(self):
self.driver.find_element_by_link_text("New whatsit").click()
# ...
To share this behavior across test cases, just use inheritance:
class BaseTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.driver = webdriver.Firefox()
def setUp(self):
self.driver.get("http://www.example.com")
self.driver.find_element_by_link_text("Log in").click()
# ...
def tearDown(self):
self.driver.get("about:blank")
@classmethod
def tearDownClass(cls):
cls.driver.quit()
class WidgetsTestCase(BaseTestCase):
def test_creating_a_widget(self):
self.driver.find_element_by_link_text("New widget").click()
# ...
class WhatsitsTestCase(BaseTestCase):
def test_creating_a_whatsit(self):
self.driver.find_element_by_link_text("New whatsit").click()
# ...
For tests that use Selenium, capybara-py may be better. It provides a layer atop Selenium and takes care of much of this and more, e.g., transparently waiting for asynchronous behavior:
import capybara
import capybara.dsl
import unittest
class BaseTestCase(unittest.TestCase):
def setUp(self):
self.page = capybara.dsl.page
self.page.visit("http://www.example.com")
self.page.click_link("Log in")
# ...
def tearDown(self):
capybara.reset_sessions()
class WidgetsTestCase(BaseTestCase):
def test_creating_a_widget(self):
self.page.click_link("New widget")
# ...
class WhatsitsTestCase(BaseTestCase):
def test_creating_a_whatsit(self):
self.page.click_link("New whatsit")
# ...
Upvotes: 1
Reputation: 51
Based on my understanding of your requirement. I would suggest this approach:
Create Login Class with a method to return driver. (Here, you initialize a driver and return it. So, you can use the same browser while using other classes also)
For all your six Classes, define methods which take driver as a parameter and return the same after statements. (So, every time you call these methods, you can give your driver to them) Note: you don't need to write Login statements again.
Finally, write a new script which imports all the classes you have created. Here initialize a Login Class and get driver handler by calling log method (based on your Login Class). Then call other methods from any class that you want by providing the driver you received as an argument.
i. Since you are initializing firefox driver in both Login and ClassName1, two sessions are created. You should avoid initializing driving in ClassName because you have already specific code for it in Login Class.
ii. Yes, you can test all the classes with one browser session using above guidelines.
Hope this helps to organize your code.
Upvotes: 0