Py.test fixture: Use function fixture in scope fixture Py.test fixture: Use function fixture in scope fixture selenium selenium

Py.test fixture: Use function fixture in scope fixture


You will need to use a workaround. The action needs to be done in a function scoped fixture with autouse set to True.

You need to initialize a variable in session based fixture, which will check if the settings have been done or not. If not done, then you will do the settings and change the flag to False

Below is a working example

import pytest@pytest.fixture(scope="session", autouse=True)def settings_page():    config = {"config_done": False}    return config@pytest.fixture()def init(request):    print("init called")    return "init"@pytest.fixture()def driver():    print("driver called")    return "driver"@pytest.fixture(autouse=True)def init_settings(settings_page, driver):    if not settings_page["config_done"]:        print("Settings being done only the first time")        settings_page["config_done"] = True@pytest.fixture()def login():    print("login called")    return "login"@pytest.fixture()def logged_in_driver(init, driver, login):    print("logged in driver is ready")    return (init, driver, login)@pytest.fixture()def non_logged_in_driver(init, driver):    print("non logged in driver is ready")    return (init, driver)def test_1(logged_in_driver):    print("test_1")def test_2(non_logged_in_driver):    print("test_2")

Output is as below

test.py driver calledSettings being done only the first timeinit calledlogin calledlogged in driver is ready.test_1driver calledinit callednon logged in driver is ready.test_2

So you can see settings only happens once


This workaround tries to achieve the same result without creating a session level fixture. It answers your need for a setting that is called only once before first test case as you mentioned in your comment above.

Create a conftest.py and place the following contents:

import pytestdef pytest_sessionstart(session):    print("Initialising Session Level Settings")    login = "A specialized login"    settings(login).create_settings()@pytest.fixture()def get_driver():    print("Get Driver")@pytest.fixture()def login(get_driver):    print("Login")@pytest.fixture()def settings(login):    print("Settings")    class Setter:        def create_settings(self):            print("[Success] Settings created!")    return Setter()

You can then use this in your test like below:

def test_one(settings):    print("Test one...")def test_two(settings):    print("Test two...")

Executing the test should give an effect close to what you wanted (based on what I can infer from your given information so far).

(py362) D:\repo\git\ens_qa>py.test -sv stackoverflow\ScopeWorkaroundTests.pyInitialising Session Level SettingsSettings[Success] Settings created!============================= test session starts =============================platform win32 -- Python 3.6.2, pytest-3.2.1, py-1.4.34, pluggy-0.4.0 -- d:\virtualenv\py362\scripts\python.execachedir: .cacherootdir: D:\repo\git\ens_qa, inifile:collected 2 itemsstackoverflow/ScopeWorkaroundTests.py::test_one Get DriverLoginSettingsTest one...PASSEDstackoverflow/ScopeWorkaroundTests.py::test_two Get DriverLoginSettingsTest two...PASSED========================== 2 passed in 0.05 seconds ===========================(py362) D:\repo\git\ens_qa>


I think the easiest way to do it, is to add some flag and use autouse like below:

import pytestflag = True@pytest.fixture()def get_driver():    pass@pytest.fixture()def login(get_driver):    pass@pytest.fixture()def settings(login):    pass@pytest.fixture(autouse = True)def setup(settings):    global flag    if flag:        settings.create_settings()        flag = False    pass