Ticket #12542: t12542-r12278.1.2.diff

File t12542-r12278.1.2.diff, 7.3 KB (added by russellm, 6 years ago)

RC1 of a patch allowing for test mirrors for testing master/slave setups

  • django/db/utils.py

    diff -r d205a9ab4b3b django/db/utils.py
    a b  
    6565        conn.setdefault('TEST_CHARSET', None)
    6666        conn.setdefault('TEST_COLLATION', None)
    6767        conn.setdefault('TEST_NAME', None)
     68        conn.setdefault('TEST_MIRROR', None)
    6869        conn.setdefault('TIME_ZONE', settings.TIME_ZONE)
    6970        for setting in ('NAME', 'USER', 'PASSWORD', 'HOST', 'PORT'):
    7071            conn.setdefault(setting, '')
  • django/test/simple.py

    diff -r d205a9ab4b3b django/test/simple.py
    a b  
    231231    def setup_databases(self):
    232232        from django.db import connections
    233233        old_names = []
     234        mirrors = []
    234235        for alias in connections:
    235236            connection = connections[alias]
    236             old_names.append((connection, connection.settings_dict['NAME']))
    237             connection.creation.create_test_db(self.verbosity, autoclobber=not self.interactive)
    238         return old_names
     237            # If the database is a test mirror, redirect it's connection
     238            # instead of creating a test database.
     239            if connection.settings_dict['TEST_MIRROR']:
     240                mirrors.append((alias, connection))
     241                mirror_alias = connection.settings_dict['TEST_MIRROR']
     242                connections._connections[alias] = connections[mirror_alias]
     243            else:
     244                old_names.append((connection, connection.settings_dict['NAME']))
     245                connection.creation.create_test_db(self.verbosity, autoclobber=not self.interactive)
     246        return old_names, mirrors
    239247
    240248    def run_suite(self, suite):
    241249        return DjangoTestRunner(verbosity=self.verbosity, failfast=self.failfast).run(suite)
    242250
    243     def teardown_databases(self, old_names):
     251    def teardown_databases(self, old_config):
     252        from django.db import connections
     253        old_names, mirrors = old_config
     254        # Point all the mirrors back to the originals
     255        for alias, connection in mirrors:
     256            connections._connections[alias] = connection
     257        # Destroy all the non-mirror databases
    244258        for connection, old_name in old_names:
    245259            connection.creation.destroy_test_db(old_name, self.verbosity)
    246260
     
    273287
    274288        suite = self.build_suite(test_labels, extra_tests)
    275289
    276         old_names = self.setup_databases()
     290        old_config = self.setup_databases()
    277291
    278292        result = self.run_suite(suite)
    279293
    280         self.teardown_databases(old_names)
     294        self.teardown_databases(old_config)
    281295
    282296        self.teardown_test_environment()
    283297
  • docs/ref/settings.txt

    diff -r d205a9ab4b3b docs/ref/settings.txt
    a b  
    359359
    360360.. setting:: TEST_NAME
    361361
     362TEST_MIRROR
     363~~~~~~~~~~~
     364
     365Default: ``None``
     366
     367The alias of the database that this database should mirror during
     368testing.
     369
     370This setting exists to allow for testing of master/slave
     371configurations of multiple databases. See the documentation on
     372:ref:`testing master/slave configurations
     373<topics-testing-masterslave>`. for details
     374
    362375TEST_NAME
    363376~~~~~~~~~
    364377
  • docs/topics/testing.txt

    diff -r d205a9ab4b3b docs/topics/testing.txt
    a b  
    301301when all the tests have been executed.
    302302
    303303By default the test databases get their names by prepending ``test_``
    304 to the value of the :setting:`NAME`` settings for the databased
     304to the value of the :setting:`NAME` settings for the databases
    305305defined in :setting:`DATABASES`. When using the SQLite database engine
    306306the tests will by default use an in-memory database (i.e., the
    307307database will be created in memory, bypassing the filesystem
    308308entirely!). If you want to use a different database name, specify
    309 ``TEST_NAME`` in the dictionary for any given database in
     309:setting:`TEST_NAME` in the dictionary for any given database in
    310310:setting:`DATABASES`.
    311311
    312312Aside from using a separate database, the test runner will otherwise
     
    325325:ref:`settings documentation <ref-settings>` for details of these
    326326advanced settings.
    327327
     328.. _topics-testing-masterslave:
     329
     330Testing master/slave configurations
     331~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     332
     333.. versionadded:: 1.2
     334
     335If you're testing a multiple database configuration with master/slave
     336replication, this strategy of creating test databases poses a problem.
     337When the test databases are created, there won't be any replication,
     338and as a result, data created on the master won't be seen on the
     339slave.
     340
     341To compensate for this, Django allows you to define that a database is
     342a *test mirror*. Consider the following (simplified) example database
     343configuration::
     344
     345    DATABASES = {
     346        'default': {
     347            'ENGINE': 'django.db.backends.mysql',
     348            'NAME': 'myproject',
     349            'HOST': 'dbmaster',
     350             # ... plus some other settings
     351        },
     352        'slave': {
     353            'ENGINE': 'django.db.backends.mysql',
     354            'NAME': 'myproject',
     355            'HOST': 'dbslave',
     356            'TEST_MIRROR': 'default'
     357            # ... plus some other settings
     358        }
     359    }
     360
     361In this setup, we have two database servers: ``dbmaster``, described
     362by the database alias ``default``, and ``dbslave`` described by the
     363alias ``slave``. As you might expect, ``dbslave`` has been configured
     364by the database administrator as a read slave of ``dbmaster``, so in
     365normal activity, any write to ``default`` will appear on ``slave``.
     366
     367If Django created two independent test databases, this would break any
     368tests that expected replication to occur. However, the ``slave``
     369database has been configured as a test mirror (using the
     370:setting:`TEST_MIRROR` setting), indicating that under testing,
     371``slave`` should be treated as a mirror of ``default``.
     372
     373When the test environment is configured, a test version of ``slave``
     374will *not* be created. Instead the connection to ``slave``
     375will be redirected to point at ``default``. As a result, writes to
     376``default`` will appear on ``slave`` -- but because they are actually
     377the same database, not because there is data replication between the
     378two databases.
     379
    328380Other test conditions
    329381---------------------
    330382
     
    13491401
    13501402    Creates the test databases.
    13511403
    1352     Returns the list of old database names that will need to be restored
     1404    Returns a data structure that provides enough detail to undo the changes
     1405    that have been made. This data will be provided to the ``teardown_databases()``
     1406    function at the conclusion of testing.
    13531407
    13541408.. method:: DjangoTestSuiteRunner.run_suite(suite)
    13551409
     
    13571411
    13581412    Returns the result produced by the running the test suite.
    13591413
    1360 .. method:: DjangoTestSuiteRunner.teardown_databases(old_names)
     1414.. method:: DjangoTestSuiteRunner.teardown_databases(old_config)
    13611415
    1362     Destroys the test databases, restoring the old names.
     1416    Destroys the test databases, restoring pre-test conditions.
     1417
     1418    ``old_config`` is a data structure defining the changes in the
     1419    database configuration that need to be reversed. It is the return
     1420    value of the ``setup_databases()`` method.
    13631421
    13641422.. method:: DjangoTestSuiteRunner.teardown_test_environment()
    13651423
Back to Top