Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Session scoped selenium fixture #59

Closed
germanp opened this issue Mar 22, 2016 · 15 comments
Closed

Session scoped selenium fixture #59

germanp opened this issue Mar 22, 2016 · 15 comments

Comments

@germanp
Copy link

germanp commented Mar 22, 2016

Hi!

Is there any way to use only one selenium instance for running various tests? I found that the selenium fixture is scoped by default as function level. But I could not found any way to overtake this using any pytest functionality.

Thanks

@ProProgrammer
Copy link

Instantiate the selenium driver in conftest.py as a fixture and set scope to session to use same driver instance throughout the session.
That's how I use it at my work.

@ProProgrammer
Copy link

This is not an issue. Please close it if this solves your query.

@davehunt
Copy link
Contributor

This is also how I would do it too, although I always recommend a fresh browser instance for each test. If you reuse the browser you risk session state affecting later tests.

@germanp
Copy link
Author

germanp commented Mar 22, 2016

Sorry, but I couldn't catch the idea. What do you mean by instantiate the selenium driver? Do you mean pasting the implementations from python_selenium.drivers?

I've tried several ways and I always get ScopeMismatch exception. The only way I found to work was to change the scope in the plugin's code.

Thanks!

@ProProgrammer
Copy link

Hi,
I meant having a fixture like this in your conftest.py file.

@pytest.fixture(scope="session")
def driver(request):
    _driver = webdriver.Firefox() # This line creates a webdriver instance
    _driver.implicitly_wait(200)
    _driver.maximize_window()
    _driver.get('https://www.google.com')
    request.addfinalizer(_driver.quit)
    return _driver

@davehunt
Copy link
Contributor

Here's an alternative conftest.py solution that doesn't require you to instantiate your own WebDriver instance:

import pytest


@pytest.fixture(scope='session')
def selenium(request):
    from pytest_selenium import selenium
    return selenium(request)


@pytest.fixture(scope='session')
def firefox_driver(request, capabilities, driver_path, firefox_profile):
    from pytest_selenium.drivers.firefox import firefox_driver
    return firefox_driver(request, capabilities, driver_path, firefox_profile)


@pytest.fixture(scope='session')
def capabilities(request, session_capabilities):
    from pytest_selenium import capabilities
    return capabilities(request, session_capabilities)


@pytest.fixture(scope='session')
def driver_path(request):
    from pytest_selenium import driver_path
    return driver_path(request)


@pytest.fixture(scope='session')
def firefox_profile(request):
    from pytest_selenium.drivers.firefox import firefox_profile
    return firefox_profile(request)

Note that I've just used the Firefox driver here, if you needed another driver you'd have to override more fixtures.

@germanp
Copy link
Author

germanp commented Mar 23, 2016

Thank you Dave. That was really useful!

@andreymal
Copy link

Proposed solution is very uncomfortable, unreliable and non-extendible, please implement scope="session" as pytest option or similar simple way as possible

@davehunt
Copy link
Contributor

Unfortunately there is no way in pytest to dynamically change the scope of fixtures. If this changes, then perhaps there will be a more elegant solution. I would still suggest that reusing a browser between tests is a bad practice, and is not an intended use case for this plugin.

@adamdorfman
Copy link

What fixtures would I need to modify to get it working with google chrome?

@bersace
Copy link

bersace commented Dec 14, 2018

That would be great to be able to choose between a scoped driver (per test) and a global driver (per session), for example with different fixture.

def test_pouet(scoped_selenium):
     scoped_selenium.get('https://example.com')

def test_login(global_selenium):
    global_selenium.find_element_by_css_selector("#loginform").submit()

@bersace
Copy link

bersace commented Dec 14, 2018

I would still suggest that reusing a browser between tests is a bad practice, and is not an intended use case for this plugin.

@davehunt can you elaborate ? I'm curious about the why.

@davehunt
Copy link
Contributor

Reusing the browser means you'll have an unknown state for each test, especially if your tests do not run in a predictable order. By restarting the browser you get a fresh profile and none of the browsing history or state from earlier tests. For me, the cost of restarting the browser has always been acceptable, especially as multiple browser instances can be running in parallel.

Also, this issue is closed, and there's now #151 which is exploring implementing a way for the user to choose the scope of the browser instance. I've never been against it being possible in the plugin, I just don't want it to be the default (or only) option to have the browser session/module/class scoped.

@bersace
Copy link

bersace commented Dec 14, 2018

Thanks @davehunt for the details!

Nightwatch for exemple allows to split tests in several steps without restarting the session. ending the session is left to the test writer. This is much useful for end-to-end test where you can have very long scenarios like web wizards. I think it make sense to preserve session between tests. It's not only about performances. end to end tests are not unit tests. What do you think about this ?

As a side note, I don't buy parallelism to be a solution. I want to write software as efficient as possible to limit IT impact on earth. 🌳 I agree that parallelism can solve performance issue if you need full isolation. Thus the idea of scoped_selenium fixture. selenium fixture looks global from my experience of e2e tests.

I read #151 before commenting (and i also avoided commenting duplicates). Maybe that would be kind to avoid every project to copy-paste something like:

@pytest.fixture(scope='session')
def session_selenium(driver_factory):
    yield driver_factory()

Anyway, #151 is a good step for this issue. Thanks for keeping it open :-)

@sontek
Copy link

sontek commented Dec 27, 2018

I'd love to get a session scoped fixture without having to define everything inside pytest selenium as well! If we can get the driver factory that would be perfect for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants