Login

Use DB Test Runner

Author:
powderflask
Posted:
December 26, 2015
Language:
Python
Version:
1.7
Score:
0 (after 0 ratings)

Use Case: Specify the DB to run tests against. For example, use a legacy DB (un-managed), or a read-only DB where it is un-important to test creation, but important to test connection, trigger functions, and that models match schema.

Usage: in DATABASES setting, add:

'TEST' :{
    'USEDB': 'your_test_DB_name_here',
}

and setting: TEST_RUNNER = 'your_app.test_runner.UseDBTestRunner'

Advantages over --keepdb:

  1. DB specific setting for multi-DB setup (e.g., default can use normal test DB, while legacy can use a pre-existing table).
  2. Can specify any DB table, including the one used by the app (for non-destructive tests, or dev DB)
  3. Allows testing against DB where creation or copying is prohibitive.
 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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
class UseDBTestRunner(DiscoverRunner):
    """
    Test runner that looks for an optional DATABASES['TEST']['USEDB'] setting.
    The value of this setting provides the DB name to use for testing.
    """
    def setup_databases(self, **kwargs):
        return setup_databases(
            self.verbosity, self.interactive, self.keepdb, self.debug_sql,
            **kwargs
        )


def setup_databases(verbosity, interactive, keepdb=False, debug_sql=False, **kwargs):
    """    This code is a copy of django.test.runner.setup_databases with a few minor tweaks. """
    from django.test.runner import dependency_ordered

    from django.db import connections, DEFAULT_DB_ALIAS
    # First pass -- work out which databases actually need to be created,
    # and which ones are test mirrors or duplicate entries in DATABASES
    mirrored_aliases = {}
    test_databases = {}
    dependencies = {}
    default_sig = connections[DEFAULT_DB_ALIAS].creation.test_db_signature()
    for alias in connections:
        connection = connections[alias]
        test_settings = connection.settings_dict['TEST']
        if test_settings['MIRROR']:
            # If the database is marked as a test mirror, save
            # the alias.
            mirrored_aliases[alias] = test_settings['MIRROR']
        else:
            # Store a tuple with DB parameters that uniquely identify it.
            # If we have two aliases with the same values for that tuple,
            # we only need to create the test database once.
            item = test_databases.setdefault(
                connection.creation.test_db_signature(),
                (connection.settings_dict['NAME'], set())
            )
            item[1].add(alias)

            if 'DEPENDENCIES' in test_settings:
                dependencies[alias] = test_settings['DEPENDENCIES']
            else:
                if alias != DEFAULT_DB_ALIAS and connection.creation.test_db_signature() != default_sig:
                    dependencies[alias] = test_settings.get('DEPENDENCIES', [DEFAULT_DB_ALIAS])

    # Second pass -- actually create the databases.
    old_names = []
    mirrors = []

    for signature, (db_name, aliases) in dependency_ordered(
            test_databases.items(), dependencies):
        test_db_name = None
        # Actually create the database for the first connection
        for alias in aliases:
            connection = connections[alias]

            #  The following code block handles the "USEDB" setting
            try:
                usedb = connection.settings_dict['TEST']['USEDB']
            except KeyError:
                usedb = None
            #print('TEST USEDB setting: ', usedb)
            if usedb:
                test_db_name = usedb
                destroy = False

            # back to duplicated code...
            elif test_db_name is None:
                test_db_name = connection.creation.create_test_db(
                    verbosity,
                    autoclobber=not interactive,
                    keepdb=keepdb,
                    serialize=connection.settings_dict.get("TEST", {}).get("SERIALIZE", True),
                )
                destroy = True
            else:
                connection.settings_dict['NAME'] = test_db_name
                destroy = False
            old_names.append((connection, db_name, destroy))

    for alias, mirror_alias in mirrored_aliases.items():
        mirrors.append((alias, connections[alias].settings_dict['NAME']))
        connections[alias].settings_dict['NAME'] = (
            connections[mirror_alias].settings_dict['NAME'])

    if debug_sql:
        for alias in connections:
            connections[alias].force_debug_cursor = True
    return old_names, mirrors

More like this

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

Comments

Please login first before commenting.