Reputation: 37
Found many topics about this problem, but didn't find any easy described problem solving, so creating new topic with this problem and maybe will get much better answer to this problem.
I have created test case for LoginTest and test case for LegalPersonSearchTest. Both these test cases are in separate files login.py and legalPersonSearch.py
from utils.utils import *
from selenium import webdriver
from locators.locators import Locators
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import unittest
from pages.loginPage import LoginPage
class LoginTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.driver = webdriver.Firefox()
cls.driver.implicitly_wait(10)
cls.driver.maximize_window()
cls.driver.get(URL)
def test_valid_login(self):
driver = self.driver
login = LoginPage(driver)
login.fill_login_form(adminUsername, adminPassword)
login.click_login_button()
if __name__ == '__main__':
unittest.main()
I think the reason why new browser opens between tests, is declaring driver in second file.
from selenium import webdriver
import unittest
from pages.legalPersonSearchPage import LegalPersonSearchPage
class LegalPersonSearchTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.driver = webdriver.Firefox()
def test_valid_organization_search(self):
driver = self.driver
legal = LegalPersonSearchPage(driver)
legal.open_legal_person_search_page()
@classmethod
def tearDown(cls):
cls.driver.quit()
if __name__ == '__main__':
unittest.main()
How to modify LoginTest that browser open only one time, instead between tests?
I need to modify it, because after login (which is 1/2 of test) comes second part of test. It will complete and then browser closes and open new and start again with login.
As someone told me, then best practice is to keep login test part out of whole test.
Upvotes: 1
Views: 1359
Reputation: 5909
To answer one of your questions -- driver
gets opened twice because you have two different setUp()
methods, one for each of your classes - LoginTest
and LegalPersonSearchTest
. When you run test_valid_login
, your setUpClass()
method gets called, which initializes the driver
. Then, test runs. This driver
instance never gets torn down, so window remains open.
Then, test_valid_organization_search
runs. This class ALSO has its own setUpClass()
method, which initializes another driver
instance. So now you have two drivers, both of which are opened in the setUpClass()
method of each class file.
This set up is producing results that you have not intended. I think you are slightly misunderstanding what "best practice is to keep login test part out of whole test" means here.
This does not mean you need to write two separate tests -- one that logs in, and one that tests the rest of the functionality. This is actually bad practice, because you want your test cases to run independently of one another -- test cases should not rely on previous test cases to execute properly.
I think the solution you are looking for here is to write the login functionality into your setUp()
method so that login is always performed before a test case starts.
This approach will prevent you from having the login part in with the test -- that's the original goal you mentioned here.
You can adjust your classes by removing the duplicate setUp()
method, and inheriting LoginTest
into your LegalPersonSearchTest
so that you are only setting up once:
from utils.utils import *
from selenium import webdriver
from locators.locators import Locators
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import unittest
from pages.loginPage import LoginPage
# this is our "base" class
class LoginTest(unittest.TestCase):
driver = None # driver instance that we will inherit into LegalPersonSearchTest
# initialize driver, go to testing URL, etc.
def setUp(cls):
cls.driver = webdriver.Firefox()
cls.driver.implicitly_wait(10)
cls.driver.maximize_window()
cls.driver.get(URL)
# call login here to login before test
login_page = LoginPage(cls.driver)
login_page .fill_login_form(adminUsername, adminPassword)
login_page .click_login_button()
# move teardown into same class as setUp()
def tearDown(cls):
cls.driver.quit()
We have declared a class variable for driver
that you can pass into LegalPersonSearchTest
. We have also removed the __main__
call, because the only entry point we need is the test_
method in LegalPersonSearchTest
:
from selenium import webdriver
import unittest
from pages.legalPersonSearchPage import LegalPersonSearchPage
from login_test import LoginTest # unsure of file name containing LoginTest class
class LegalPersonSearchTest(LoginTest): # inherit LoginTest here so we can use driver
def test_valid_organization_search(self):
legal_page = LegalPersonSearchPage(self.driver)
legal_page .open_legal_person_search_page()
if __name__ == '__main__':
unittest.main()
We have changed a few things here:
__main__
-- we only need this in one place, on the test case level (LegalPersonSearchTest
)setUp()
method calls that were resulting in multiple driver instances getting created (mentioned in your problem description)LoginTest
class to be passed into LegalPersonSearchTest
classsetUp()
method on LoginTest
to initialize the driver and login -- so that you do not have to include login code for any test!Update: Changes made following comments:
login
method from LoginTest
class and moved login code under setUp()
-- this will get performed before every test case nowtest_valid_organization_search
to use self.driver
instead of driver
when initializing PageObjectI've made many of these changes based on this sample Python test architecture that I pushed to my GitHub. The files I used as templates were base_test_fixture.py
(for your LoginTest
), and test_web_driver.py
for your LegalPersonSearchTest
.
You may notice that base_test_fixture.py
also contains def _testInitialize()
and def _testCleanup()
-- these are methods that you can override in your LegalPersonSearchTest
class to perform additional steps to be run before your test_
method. The idea here is that if you have multiple .py
files containing test cases, but each .py
file requires slightly different setup, and you need to do more than just setUp()
method calls for. You can override the testInitialize()
and testCleanup()
methods in the test case class, and these methods will execute after setUp()
and before the actual test_
method.
Let me know if you have any questions about this -- it's quite a bit to explain, but once you learn this architecture, you have a very powerful way of organizing and executing your test cases.
Upvotes: 1