Home > front end >  Pytest, selenium, fixture throws an error after the first test InvalidSessionIdException
Pytest, selenium, fixture throws an error after the first test InvalidSessionIdException

Time:08-22

I have a fixture file.

import pytest
from selenium.webdriver.chrome.options import Options as chrome_options
from driver.singleton_driver import WebDriver


@pytest.fixture
def get_chrome_options():
    options = chrome_options()
    options.add_argument('chrome')
    options.add_argument('--start-maximized')
    options.add_argument('--window-size=1920,1080')
    options.add_argument('--incognito')
    return options


@pytest.fixture
def get_webdriver(get_chrome_options):
    options = get_chrome_options
    driver = WebDriver(options).driver
    return driver


@pytest.fixture(scope='function')
def setup(request, get_webdriver):
    driver = get_webdriver
    if request.cls is not None:
        request.cls.driver = driver
    yield driver
    driver.close()

File with my tests

import pytest

@pytest.mark.usefixtures('setup')
class TestSteamPages:

    def test_first(self):
        self.driver.get('https://www.google.com/')
        

    def test_second(self):
        self.driver.get('https://www.google.com/')

As I understand it, after the first test, the function in the driver.close() fixture is triggered. But when the second test is run, the fixture does not restart the webdriver. An error

    venv/lib/python3.10/site-packages/selenium/webdriver/remote/errorhandler.py:243: InvalidSessionIdException
============================================================================== short test summary info ==============================================================================
FAILED tests/test_first.py::TestSteamPages::test_second - 

selenium.common.exceptions.InvalidSessionIdException: Message: invalid session id
ERROR tests/test_first.py::TestSteamPages::test_second - selenium.common.exceptions.InvalidSessionIdException: Message: invalid session id

For the driver, I use the Singleton pattern

from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager


class WebDriver:
    class __WebDriver:
        def __init__(self, options):
            self.driver = webdriver.Chrome(options=options, service=ChromeService(ChromeDriverManager().install()))

    driver = None

    def __init__(self, options):
        if not self.driver:
            WebDriver.driver = WebDriver.__WebDriver(options=options).driver

CodePudding user response:

The driver is not reinitialized because of the singleton. WebDriver.driver is initialized before first test, so in the next time setup is running if not self.driver is False, because self.driver is not None anymore.

If you want to initialize the WebDriver every test don't use singleton

@pytest.fixture
def get_webdriver(get_chrome_options):
    options = get_chrome_options
    driver = webdriver.Chrome(options=options, service=ChromeService(ChromeDriverManager().install()))
    return driver

If you do want to initialize the WebDriver only once you can change fixtures scope to 'class' (for all tests in TestSteamPages) or even move it to conftest.py with scope 'session' for one driver instance for all the test. Note that in this case all the fixtures need to have scope='class'

@pytest.fixture(scope='class')
def setup(request, get_webdriver):
    driver = get_webdriver
    if request.cls is not None:
        request.cls.driver = driver
    yield driver
    driver.close()
  • Related