Login

Test runner that installs 'tests' packages as apps

Author:
adrian_lc
Posted:
September 24, 2013
Language:
Python
Version:
1.5
Score:
1 (after 1 ratings)

Ever tried to unit test custom fields or abstract models? If so, you probably used a solution like this one. It surely works, but it has some issues:

  1. Runs 'syncdb' several times.
  2. It's not automatic. You must add the mixin or copy the code to each of the TestCases.

This test runner adds to INSTALLED_APPS the 'app.tests' package for each of the specified apps, before the 'syncdb' happens.

This has the discovery runner as a dependency (for 1.5 only, it will be the default in 1.6). However, it comes as a mixin so it should be easily pluggable to other test runners.

If you intend to use the mixin with other runners, note that it imports 'app.tests.models' so it won't work with tests modules (tests.py). Your runner must "use" test packages (like discovery runner).

USAGE

# in your settings.py:
TESTAPPS_INSTALL = (
    'app1',
    'app2',
    # ...
)
TEST_RUNNER = 'testapp_runner.DiscoverTestAppRunner'  # example import path

# extra apps in command line.
# run test for apps 'app1' to 'app4', adding 'app3' and 'app4' to the TESTAPPS_INSTALL setting.
manage.py test app1 app2 app3 app4 --with-test-app=app3 --with-test-app=app4
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
from optparse import make_option

from django.conf import settings
from django.db.models.loading import load_app
from django.utils.importlib import import_module


try:
    # Django 1.6
    from django.test.runner import DiscoverRunner
except ImportError:
    # Fallback to third-party app on Django 1.5
    from discover_runner import DiscoverRunner


TESTAPPS_INSTALL = list(getattr(settings, 'TESTAPPS_INSTALL', () ))


class TestAppRunnerMixin(object):

    """
    A Django test runner mixin that, before testing and prior to 'syncdb', installs
    the 'tests' package from each of the apps specified.
    """

    option_list = (
        make_option(
            '--with-test-app',
            action='append',
            choices=settings.INSTALLED_APPS,
            dest='which_apps',
            default=settings.TESTAPPS_INSTALL,
            help="Specify a subset of INSTALLED_APPS whose 'tests' modules MUST be installed"
                 " as apps during test execution."
        ),
    )

    def __init__(self, which_apps, **options):
        self.which_apps = set(which_apps)  # remove duplicates
        super(TestAppRunnerMixin, self).__init__(**options)

    def setup_test_environment(self, **kwargs):
        self.install_test_apps()
        super(TestAppRunnerMixin, self).setup_test_environment(**kwargs)

    def install_test_apps(self):
        test_apps = []
        for app in self.which_apps:
            try:
                test_app = import_module('.tests', app)
                # check if it has a 'models' module and, if so, add it to the 'AppCache':
                if load_app(test_app.__name__):
                    test_apps.append(test_app.__name__)
            except ImportError:
                pass  # app with no 'tests' module
        settings.INSTALLED_APPS += tuple(test_apps)


class DiscoverTestAppRunner(TestAppRunnerMixin, DiscoverRunner):
    option_list = DiscoverRunner.option_list + TestAppRunnerMixin.option_list

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 3 months, 1 week ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 3 months, 2 weeks ago
  3. Serializer factory with Django Rest Framework by julio 10 months, 1 week ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 11 months ago
  5. Help text hyperlinks by sa2812 11 months, 3 weeks ago

Comments

Please login first before commenting.