Reputation: 189
I'm trying to make my selenium test as atomic and independent of each other as possible so I decided to quit the browser and create a new Webdriver instance after each test runs. This approach made the more sense to me and was reinforced by several threads discussing this issue. e. g. This answer to a related question:
You are closing the webdriver after one particular test. This is a good approach but you will need to start a new webdriver for each new test that you want to run.
However, I've also come across the opinion that quitting the browser after each test is unnecessary and ineffective. e. g. Part of this blog about Selenium:
It’s not good practice to load a browser before each test. Rather, it is much better to load a browser before all tests and then close it after all tests are executed, as this will save resources and test execution time.
As I'm pretty new to all of this, I'm struggling to choose between these two. So far the execution time of my tests is not a real concern (as I only have a handful of them) but as I begin to expand my test suite I'm worried that it might become an issue.
Upvotes: 7
Views: 5156
Reputation: 123
DebanjanB has a great answer. I am of the cloth that there is no one-sized-fits-all answer.
There is some fun balance to be had. Depending on what framework you are using, you could get fancy. I like pytest for it's unique use of fixtures.
To this end, you could do tests, or sets of tests either way depending on what you need. You could balance browser load times vs execution for what makes sense.
As an example in pytest:
conftest.py:
import pytest
from selenium import webdriver
@pytest.fixture(scope='module')
def module_browser(request):
"""Fixture lasts for an entire file of tests."""
driver = webdriver.Chrome()
def fin():
driver.quit()
request.addfinalizer(fin())
return driver
@pytest.fixture(scope='function')
def function_browser(request):
"""Fixture lasts for just a test function."""
driver = webdriver.Chrome()
def fin():
driver.quit()
request.addfinalizer(fin())
return driver
Now module_browser()
lets you get a browser for a whole test module.
funtion_browser()
gives you a new browser per test function.
Lets get fancy.. you have a bunch of tests that need to be logged in, and they are doing cosmetic checks on a standard account:
conftest.py continued...
@pytest.fixture(scope='module')
def logged_in_browser(request):
"""Provide a logged in browser for simple tests."""
driver = webdriver.Opera()
# Now go and log this browser in,
# so we can use the logged in state for tests.
log_in_browser(username='RedMage', password='masmune')
def fin():
driver.quit()
request.addfinalizer(fin())
return driver
This is about the same, but lets you have a browser stay open for a few tests, and it's logged in. If logging in takes say 5 seconds, and you have 30 tests that atomically check cosmetic things, you can shave a few minutes.
This flexibility will let you run some tests faster, and some tests in a more clean state. We might need some of each to run a suite and still be able to get efficiency gains on the time. There is no one-sized-fits-all answer.
Utilizing fixture in pytest lets you choose what you want for each test.. if it should be a clean browser, or if it needs to be faster.
Then in the tests we see stuff like this: test_things.py
def test_logged_out_assets(function_browser):
driver = function_browser # just for clarity here.
driver.get('http://example.com/')
check_some_stuff(driver)
language_subdomain_list = ['www', 'es', 'de', 'ru', 'cz']
@pytest.parametrize(language_subdomain, language_subdomain_list)
def test_logged_out_assets_multlingual(module_browser, language_subdomain):
"""
Check the assets come up on each language subdomain.
This test will run for each of the subdomains as separate tests.
5 in all.
"""
driver = module_browser # for clarity in example.
url = "http://{}.example.com".format(language_subdomain)
driver.get(url)
check_some_stuff(driver)
def test_logged_in_assets(logged_in_browser):
"""
Check specific assets while logged in.
Remember, our web browser already is logged in when we get it!
"""
driver = logged_in_browser # for clarity in example.
check_some_assets(driver)
Py.test Fixtures: https://docs.pytest.org/en/latest/fixture.html
Upvotes: 3
Reputation: 193388
Answering straight, factually there is no definite rules to quit or reuse the same browser client while executing the tests using Selenium. Perhaps the decision would be based on the pre-requisites of the testcases.
If your tests are independent, it would be wise to to quit()
the current Webdriver and Browser Client instance and create a new instance of the Webdriver and Browser Client after each test runs which will initiate a new and clean WebDriver / Browser Client combination as discussed in closing browser after test pass.
Albeit it would induce some overhead to spawn the new WebDriver / Browser Client combination but that may provide the much needed cushion from CPU and Memory usage as discussed in:
Incase, the tests are not independent and the tests are based on the same session, cookies, etc parameters, reusing the same WebDriver / Browser Client makes sense.
Upvotes: 5