Using Pytest fixtures, I'm looking for a way to pass settings overrides to my application fixtures, so I can test different settings without having to define different fixtures.
I'm using a common pattern when creating tests for Flask is to initialize the app and the database like follows. Notice that the db
fixture hard-codes the app
fixture as an argument.
from myapp import create_app
@pytest.fixture
def app():
settings_override = {} # By setting values here, I can pass in different Flask config variables
app = create_app(settings_override)
return app
@pytest.fixture
def db(app):
do_something_to_create_the_database(app) # app needed for context
yield db
And then, a number of tests might use the fixtures defined above such as.
def test_my_application_1(db, app):
...
def test_my_application_2(db, app):
...
Let's say I want to initialize the app fixture with different settings, and let's say I can pass those settings into the create_app() function defined above. On a per-test basis, how can a attach the app
and db
fixtures such that I can pass in settings overrides to the app
fixture? Is there a way I can parameterize the fixture at a test case level so I can pass in different settings to the fixture?
i.e.
# for this test, I want to pass the BAZ=True setting to the app fixture.
def test_my_application_1(db, app):
...
# for this test, I want to pass FOO=BAR setting to the app fixture
def test_my_application_2(db, app):
...
I appreciate any advice you have to offer.
Update: with solution from @mrbean-bremen
Thanks to @MrBean Bremen for the elegant solution. With a slight modification using the hasattr, I was able to extend the solution to accept parameter overrides or to accept a default.
@pytest.fixture(scope='function')
def app(request):
settings_override = {
'SQLALCHEMY_DATABASE_URI': "sqlite:///:memory:",
}
params = request.param if hasattr(request, 'param') else {}
return create_app({**settings_override, **params})
@pytest.fixture(scope='function')
def db(app):
with app.app_context():
....
def test_without_params(db, app):
...
@pytest.mark.parametrize("app", [{'DEBUG': True}], indirect=True)
def test_with_overrides(db, app):
...