I have an ETL build with sqlalchemy. To test it, we are using postgres in a docker container through pytest-docker.
But because on some computer, spinning docker container takes some time, we also have a sqlite backend.
The question is, how to conditionally select either backend without spinning the docker container with fixtures docker_ip and docker_services provided by pytest-docker?
I have the following:
@pytest.fixture(name="sqlite_db", scope="session")
def fixture_sqlite_db():
...
yield engine
@pytest.fixture(name="postgres_db", scope="session")
def fixture_postgres_db(docker_ip, docker_services):
...
yield engine
@pytest.fixture(name=mock_get_engine", scope="session")
def fixture_mock_get_engine(engine):
with pytest.MonkeyPatch.context() as mock:
mock.setattr(my_module, "get_engine", lambda: engine)
yield mock
So far, both engine fixtures were run in separate test files, with copy of all tests, with the postgres having:
if not os.getenv("TEST_POSTGRES", False):
pytest.skip("skipping postgres database tests", allow_module_level=True)
which worked, but having half of the test-suite by copy-pasted is less than ideal.
---
Is there way to select fixture conditionally?
I tried:
@pytest.fixture(name="engine", scope="module")
def fixture_engine():
if os.getenv("TEST_POSTGRES", False):
engine = fixture_postgres_db()
else:
engine = fixture_sqlite_db()
yield engine
but this didn't work.
Edit:
The build-in fixture request can be used for this. The parameterized documentation uses it in slightly different context, but never elaborates over it. Had to hard grok it :(
Using request.getfixturevalue, a fixture can be selected.
@pytest.fixture(name="engine", scope="module")
def fixture_engine(request):
if os.getenv("TEST_POSTGRES", False):
engine = request.getfixturevalue("postgres_db")
else:
engine = request.getfixturevalue("sqlite_db")
yield engine