Mo J. Mughrabi
Mo J. Mughrabi

Reputation: 6997

parameterize testing with django settings

Am working on a django reusable package that am planning to use with multiple project. I've used pytest to build test suite, I've used parametrized helped in pytest to run a single test with multiple configuration.

Yet, I would like to run all my tests using different settings combinations

available_backends = [
    'django_profile.auth_backends.drf.RestFramework',
    'django_profile.auth_backends.kong.Kong',
]


def pytest_generate_tests(metafunc):
    # if 'stringinput' in metafunc.fixturenames:
    if 'auth_backend' in metafunc.fixturenames:
        metafunc.parametrize(
            'auth_backend',
            available_backends
        )


@pytest.fixture(params=['auth_backend', ])
def auth_backend(request, settings):
    settings.DJANGO_PROFILE_AUTH_BACKEND = request.auth_backend
    return settings

I experimented with the above approach, but this also means I have to add auth_backend to each test case, I don't believe this is ideal. Any one can recommend a way for me to run all my tests using different setting combinations?

Regards

Upvotes: 4

Views: 2519

Answers (3)

you can override settings for each test.

django documentation: Overriding settings

for example:

from django.test import TestCase
class LoginTestCase(TestCase):

    def test_login(self):

        # First check for the default behavior
        response = self.client.get('/sekrit/')
        self.assertRedirects(response, '/accounts/login/?next=/sekrit/')

        # Then override the LOGIN_URL setting
        with self.settings(LOGIN_URL='/other/login/'):
            response = self.client.get('/sekrit/')
            self.assertRedirects(response, '/other/login/?next=/sekrit/')

or use for decorator

from django.test import TestCase, override_settings

class LoginTestCase(TestCase):

    @override_settings(LOGIN_URL='/other/login/')
    def test_login(self):
        response = self.client.get('/sekrit/')
        self.assertRedirects(response, '/other/login/?next=/sekrit/')

Upvotes: 2

Mo J. Mughrabi
Mo J. Mughrabi

Reputation: 6997

Eventually, I found a way to pass different settings to all tests without having to specify the fixture in each test. Below is a working example

# conftest.py
@pytest.yield_fixture(params=available_backends)
def settings(request, settings):
    if request.param not in available_backends:
        raise ValueError('auth_backend {} not implemented.'.format(request.param))
    wrapper = SettingsWrapper()
    settings.DJANGO_PROFILE_AUTH_BACKEND = request.param
    yield wrapper
    wrapper.finalize()

# setup.cfg
usefixtures = settings

Upvotes: 0

mou55
mou55

Reputation: 730

please did you try:

  • to use code in conftest.py with scope="session"
  • use available_backends list directly in params= instead of pytest_generate_tests

https://docs.pytest.org/en/latest/fixture.html#parametrizing-fixtures

if not, could you try using this:

@pytest.fixture(scope='session', params=[
    'django_profile.auth_backends.drf.RestFramework',
    'django_profile.auth_backends.kong.Kong',
])
def auth_backend(request, settings):
    settings.DJANGO_PROFILE_AUTH_BACKEND = request.param
    yield settings

Upvotes: 3

Related Questions