I'm using Python3.8 and pytest. How can I activate a fixture for my session based on some command line specification? Right now I have a tests/conftest.py file that includes
@pytest.fixture(name="fixture1", scope="session")
def fixture1():
...
@pytest.fixture(name="fixture2", scope="session")
def fixture2():
...
But I only want certain fixtures included in my session and I want to be able to specify that in either a pytest.ini file or via command line arguments I pass to pytest. How do I do that?
Edit: This is my use case ...
If the command line option is enabled, I'd like to depend on one fixture
@pytest.fixture(name="az_sql_db_inst")
def az_db_connection_fixture(az_sql_creds, wait_for_sql_server)
but if the command line isn't enabled, I'd like to depend on another fixture ...
@pytest.fixture(name="az_sql_db_inst")
def az_db_connection_fixture(az_sql_creds, wait_for_docker_sql_server)
You can add command line flags that can be used to enable your fixtures:
conftest.py
def pytest_addoption(parser):
parser.addoption('--option2', action='store_const', const=True)
parser.addoption('--option2', action='store_const', const=True)
Then you have to check for these arguments in your fixture:
@pytest.fixture(name="fixture1", scope="session", autouse=True)
def fixture1(request):
# only use with option1 command line argument
if request.config.getoption("--option1"):
...
@pytest.fixture(name="fixture2", scope="session", autouse=True)
def fixture2(request):
# only use with option2 command line argument
if request.config.getoption("--option2"):
...
@pytest.fixture(name="fixture3", scope="session", autouse=True)
def fixture3(request):
# only use if option1 command line argument is not provided
if not request.config.getoption("--option1"):
...
I used autouse=True
here as I expect that the fixtures execute different setup code, your usage may vary of course.
You are now able to call:
pytest
-> no fixture will be appliedpytest --option1
-> fixture1 will be appliedpytest --option1 --option2
-> both fixtures will be appliedYou can also add these arguments to your pytest.ini
:
[pytest]
# always apply fixture2
addopts = --option2
EDIT:
As for the followup question about the inherited fixture, you can do something like this:
@pytest.fixture
def wait_for_sql_server(request):
if request.config.getoption("--my_option"):
...
@pytest.fixture
def wait_for_docker(request):
if not request.config.getoption("--my_option"):
...
@pytest.fixture(name="az_sql_db_inst")
def az_db_connection_fixture(
az_sql_creds, wait_for_sql_server, wait_for_docker):
...
EDIT2:
If you are not able to write or adapt the base fixtures (wait_for_
in the EDIT part of the question) yourself, you can go a slighly other way.
You can write separate implementations of your base fixture in separate plugins, and load the needed plugin based on the configuration:
plugin_docker.py
@pytest.fixture
def wait_for_service(wait_for_docker):
yield
plugin_server.py
@pytest.fixture
def wait_for_service(wait_for_sql_server):
yield
conftest.py
def pytest_addoption(parser):
parser.addoption('--docker', action='store_const', const=True)
def pytest_configure(config):
use_docker = config.getoption("--docker")
plugin_name = 'plugin_docker' if use_docker else 'plugin_server'
if not config.pluginmanager.has_plugin(plugin_name):
config.pluginmanager.import_plugin(plugin_name)
@pytest.fixture(name="az_sql_db_inst")
def az_db_connection_fixture(az_sql_creds, wait_for_service):
...
The wait_for_service
fixtures are just a wrapper around the actual fixtures, but this way you can derive from the same fixture in both scenarios.