Posts>Dynaconf settings & pytest

Dynaconf settings & pytest

Marc Gibbons
Published: April 22, 2023

I recently used Dynaconf to build a sophisticated command line interface application. As the application grew in complexity, a settings management solution was required–one which could easily be extended and overridden by end-users.

Coming from Django, I yearned for a pytest fixture which behaved like settings from pytest-django.

My requirements were:

  • Provide deterministic settings for the test suite, impervious to environment-specific variations such as values set in environment variables (a feature of Dyanconf)
  • Allow settings to be customized at the test function scope
  • Clean up values between each test

The fixture itself is simple; it takes the Dynaconf instance used in the application and re-initializes it.

In this case, I reload the production settings file, and have added a test-specific settings toml file which lets us override global values. At tear down, the settings module is wiped to avoid leaks between tests.

# conftest.py

# Import the dynaconf.Dynaconf instance
from myproject.config import settings as _settings

# This examples uses separate settings files so that the test settings
# do not get packaged.
ROOT_SETTINGS = "src/myproject/settings.toml"
TEST_SETTINGS = "tests/settings.toml"

@pytest.fixture(autouse=True)
def settings():
    # Reload the "production" settings, and merge a test-specific settings
    # file. Any environment variables set are ignored.
    _settings.load_file(
      path=[ROOT_SETTINGS, TEST_SETTINGS],
      silent=False,  # Yell when there are errors!
    )
    yield _settings
    _settings.clean()  # Reset / cleanup overrides

This fixture runs at each test since autouse=True and can be pulled into individual tests to make changes.

def test_changing_my_setting(settings):
    settings.MY_SETTING = "foo"
    ...

For a practical example, check out: https://github.com/marcgibbons/dynaconf-pytest-example.