Wolkenarchitekt
Wolkenarchitekt

Reputation: 21238

Use custom test suite runner with pytest-django

I want to switch my Django (version 1.6x) application to use pytest-django for tests. Therefore I installed latest pytest-django via pip and got these versions:

pytest==2.6.4
pytest-django==2.7.0

With regular django-tests, I'm using a custom test suite runner extending DjangoTestSuiteRunner, which I configured in my settings.py:

settings.py:

TEST_RUNNER = "dcmanager.tests.runner.ManagedModelTestRunner"

runner.py:

import unittest

from django.conf import settings
from django.db.models import get_app, get_apps
from django.test.simple import DjangoTestSuiteRunner, build_test, build_suite, runner


class ManagedModelTestRunner(DjangoTestSuiteRunner):
    """
    Test runner that automatically makes all unmanaged models in
    project managed for the duration of the test run and patches VStorage model,
    so that one doesn't need to execute the SQL manually to create them.
    """
    IGNORE_TESTS = ['django', 'rest_framework', 'rest_framework_swagger']

    def build_suite(self, test_labels, extra_tests=None, **kwargs):
        suite = unittest.TestSuite()

        if test_labels:
            for label in test_labels:
                if '.' in label:
                    suite.addTest(build_test(label))
                else:
                    app = get_app(label)
                    suite.addTest(build_suite(app))
        else:
            ignore_list = []
            for app in get_apps():
                app_name_parts = app.__name__.split('.')
                for index, _ in enumerate(app_name_parts):
                    app_part_name = '.'.join(app_name_parts[0:index])
                    if app_part_name and app_part_name in self.IGNORE_TESTS:
                        ignore_list.append(app.__name__)
                        break
                if app.__name__ not in ignore_list:
                    suite.addTest(build_suite(app))

        if extra_tests:
            for test in extra_tests:
                suite.addTest(test)

        return runner.reorder_suite(suite, (unittest.TestCase,))

    def setup_test_environment(self, *args, **kwargs):
        if settings.STAGE == 'TEST':
            from django.db.models.loading import get_models
            self.unmanaged_models = [m for m in get_models()
                                     if not m._meta.managed]
            for m in self.unmanaged_models:
                m._meta.managed = True

        super(ManagedModelTestRunner, self).setup_test_environment(*args,
                                                                   **kwargs)

    def teardown_test_environment(self, *args, **kwargs):
        super(ManagedModelTestRunner, self).teardown_test_environment(*args,
                                                                      **kwargs)
        # reset unmanaged models
        for m in self.unmanaged_models:
            m._meta.managed = False

How can I tell pytest-django to use my custom test suite runner?

Upvotes: 8

Views: 2396

Answers (2)

Pithikos
Pithikos

Reputation: 20300

As Ronny mentioned py.test does not have runners but you can get the same functionality by utilizing the various things with conftest.py files inside your testsuite.

For database setup you can use the django_db_setup fixture: https://pytest-django.readthedocs.io/en/latest/database.html#django-db-setup

For more general stuff you can use a function pytest_configure in your conftest:

conftest.py

@pytest.fixture
def django_db_setup():
    # db setup

def pytest_configure(config):
    # other pytest stuff

Upvotes: 0

user78110
user78110

Reputation:

py.test does not use unit-test runners at all

i'm afraid you will have to redo the custom collection in py.test

Upvotes: 2

Related Questions