Loading django/db/utils.py +1 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ class ConnectionHandler(object): conn.setdefault('TEST_CHARSET', None) conn.setdefault('TEST_COLLATION', None) conn.setdefault('TEST_NAME', None) conn.setdefault('TEST_MIRROR', None) conn.setdefault('TIME_ZONE', settings.TIME_ZONE) for setting in ('NAME', 'USER', 'PASSWORD', 'HOST', 'PORT'): conn.setdefault(setting, '') Loading django/test/simple.py +20 −6 Original line number Diff line number Diff line Loading @@ -231,16 +231,30 @@ class DjangoTestSuiteRunner(object): def setup_databases(self): from django.db import connections old_names = [] mirrors = [] for alias in connections: connection = connections[alias] # If the database is a test mirror, redirect it's connection # instead of creating a test database. if connection.settings_dict['TEST_MIRROR']: mirrors.append((alias, connection)) mirror_alias = connection.settings_dict['TEST_MIRROR'] connections._connections[alias] = connections[mirror_alias] else: old_names.append((connection, connection.settings_dict['NAME'])) connection.creation.create_test_db(self.verbosity, autoclobber=not self.interactive) return old_names return old_names, mirrors def run_suite(self, suite): return DjangoTestRunner(verbosity=self.verbosity, failfast=self.failfast).run(suite) def teardown_databases(self, old_names): def teardown_databases(self, old_config): from django.db import connections old_names, mirrors = old_config # Point all the mirrors back to the originals for alias, connection in mirrors: connections._connections[alias] = connection # Destroy all the non-mirror databases for connection, old_name in old_names: connection.creation.destroy_test_db(old_name, self.verbosity) Loading Loading @@ -273,11 +287,11 @@ class DjangoTestSuiteRunner(object): suite = self.build_suite(test_labels, extra_tests) old_names = self.setup_databases() old_config = self.setup_databases() result = self.run_suite(suite) self.teardown_databases(old_names) self.teardown_databases(old_config) self.teardown_test_environment() Loading docs/ref/settings.txt +15 −0 Original line number Diff line number Diff line Loading @@ -357,6 +357,21 @@ Only supported for the ``mysql`` backend (see the `MySQL manual`_ for details). .. _MySQL manual: MySQL_ .. setting:: TEST_MIRROR TEST_MIRROR ~~~~~~~~~~~ Default: ``None`` The alias of the database that this database should mirror during testing. This setting exists to allow for testing of master/slave configurations of multiple databases. See the documentation on :ref:`testing master/slave configurations <topics-testing-masterslave>` for details. .. setting:: TEST_NAME TEST_NAME Loading docs/topics/testing.txt +63 −5 Original line number Diff line number Diff line Loading @@ -301,12 +301,12 @@ Regardless of whether the tests pass or fail, the test databases are destroyed when all the tests have been executed. By default the test databases get their names by prepending ``test_`` to the value of the :setting:`NAME`` settings for the databased to the value of the :setting:`NAME` settings for the databases defined in :setting:`DATABASES`. When using the SQLite database engine the tests will by default use an in-memory database (i.e., the database will be created in memory, bypassing the filesystem entirely!). If you want to use a different database name, specify ``TEST_NAME`` in the dictionary for any given database in :setting:`TEST_NAME` in the dictionary for any given database in :setting:`DATABASES`. Aside from using a separate database, the test runner will otherwise Loading @@ -325,6 +325,58 @@ control the particular collation used by the test database. See the :ref:`settings documentation <ref-settings>` for details of these advanced settings. .. _topics-testing-masterslave: Testing master/slave configurations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. versionadded:: 1.2 If you're testing a multiple database configuration with master/slave replication, this strategy of creating test databases poses a problem. When the test databases are created, there won't be any replication, and as a result, data created on the master won't be seen on the slave. To compensate for this, Django allows you to define that a database is a *test mirror*. Consider the following (simplified) example database configuration:: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'myproject', 'HOST': 'dbmaster', # ... plus some other settings }, 'slave': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'myproject', 'HOST': 'dbslave', 'TEST_MIRROR': 'default' # ... plus some other settings } } In this setup, we have two database servers: ``dbmaster``, described by the database alias ``default``, and ``dbslave`` described by the alias ``slave``. As you might expect, ``dbslave`` has been configured by the database administrator as a read slave of ``dbmaster``, so in normal activity, any write to ``default`` will appear on ``slave``. If Django created two independent test databases, this would break any tests that expected replication to occur. However, the ``slave`` database has been configured as a test mirror (using the :setting:`TEST_MIRROR` setting), indicating that under testing, ``slave`` should be treated as a mirror of ``default``. When the test environment is configured, a test version of ``slave`` will *not* be created. Instead the connection to ``slave`` will be redirected to point at ``default``. As a result, writes to ``default`` will appear on ``slave`` -- but because they are actually the same database, not because there is data replication between the two databases. Other test conditions --------------------- Loading Loading @@ -1349,7 +1401,9 @@ set up, execute and tear down the test suite. Creates the test databases. Returns the list of old database names that will need to be restored Returns a data structure that provides enough detail to undo the changes that have been made. This data will be provided to the ``teardown_databases()`` function at the conclusion of testing. .. method:: DjangoTestSuiteRunner.run_suite(suite) Loading @@ -1357,9 +1411,13 @@ set up, execute and tear down the test suite. Returns the result produced by the running the test suite. .. method:: DjangoTestSuiteRunner.teardown_databases(old_names) .. method:: DjangoTestSuiteRunner.teardown_databases(old_config) Destroys the test databases, restoring pre-test conditions. Destroys the test databases, restoring the old names. ``old_config`` is a data structure defining the changes in the database configuration that need to be reversed. It is the return value of the ``setup_databases()`` method. .. method:: DjangoTestSuiteRunner.teardown_test_environment() Loading Loading
django/db/utils.py +1 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ class ConnectionHandler(object): conn.setdefault('TEST_CHARSET', None) conn.setdefault('TEST_COLLATION', None) conn.setdefault('TEST_NAME', None) conn.setdefault('TEST_MIRROR', None) conn.setdefault('TIME_ZONE', settings.TIME_ZONE) for setting in ('NAME', 'USER', 'PASSWORD', 'HOST', 'PORT'): conn.setdefault(setting, '') Loading
django/test/simple.py +20 −6 Original line number Diff line number Diff line Loading @@ -231,16 +231,30 @@ class DjangoTestSuiteRunner(object): def setup_databases(self): from django.db import connections old_names = [] mirrors = [] for alias in connections: connection = connections[alias] # If the database is a test mirror, redirect it's connection # instead of creating a test database. if connection.settings_dict['TEST_MIRROR']: mirrors.append((alias, connection)) mirror_alias = connection.settings_dict['TEST_MIRROR'] connections._connections[alias] = connections[mirror_alias] else: old_names.append((connection, connection.settings_dict['NAME'])) connection.creation.create_test_db(self.verbosity, autoclobber=not self.interactive) return old_names return old_names, mirrors def run_suite(self, suite): return DjangoTestRunner(verbosity=self.verbosity, failfast=self.failfast).run(suite) def teardown_databases(self, old_names): def teardown_databases(self, old_config): from django.db import connections old_names, mirrors = old_config # Point all the mirrors back to the originals for alias, connection in mirrors: connections._connections[alias] = connection # Destroy all the non-mirror databases for connection, old_name in old_names: connection.creation.destroy_test_db(old_name, self.verbosity) Loading Loading @@ -273,11 +287,11 @@ class DjangoTestSuiteRunner(object): suite = self.build_suite(test_labels, extra_tests) old_names = self.setup_databases() old_config = self.setup_databases() result = self.run_suite(suite) self.teardown_databases(old_names) self.teardown_databases(old_config) self.teardown_test_environment() Loading
docs/ref/settings.txt +15 −0 Original line number Diff line number Diff line Loading @@ -357,6 +357,21 @@ Only supported for the ``mysql`` backend (see the `MySQL manual`_ for details). .. _MySQL manual: MySQL_ .. setting:: TEST_MIRROR TEST_MIRROR ~~~~~~~~~~~ Default: ``None`` The alias of the database that this database should mirror during testing. This setting exists to allow for testing of master/slave configurations of multiple databases. See the documentation on :ref:`testing master/slave configurations <topics-testing-masterslave>` for details. .. setting:: TEST_NAME TEST_NAME Loading
docs/topics/testing.txt +63 −5 Original line number Diff line number Diff line Loading @@ -301,12 +301,12 @@ Regardless of whether the tests pass or fail, the test databases are destroyed when all the tests have been executed. By default the test databases get their names by prepending ``test_`` to the value of the :setting:`NAME`` settings for the databased to the value of the :setting:`NAME` settings for the databases defined in :setting:`DATABASES`. When using the SQLite database engine the tests will by default use an in-memory database (i.e., the database will be created in memory, bypassing the filesystem entirely!). If you want to use a different database name, specify ``TEST_NAME`` in the dictionary for any given database in :setting:`TEST_NAME` in the dictionary for any given database in :setting:`DATABASES`. Aside from using a separate database, the test runner will otherwise Loading @@ -325,6 +325,58 @@ control the particular collation used by the test database. See the :ref:`settings documentation <ref-settings>` for details of these advanced settings. .. _topics-testing-masterslave: Testing master/slave configurations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. versionadded:: 1.2 If you're testing a multiple database configuration with master/slave replication, this strategy of creating test databases poses a problem. When the test databases are created, there won't be any replication, and as a result, data created on the master won't be seen on the slave. To compensate for this, Django allows you to define that a database is a *test mirror*. Consider the following (simplified) example database configuration:: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'myproject', 'HOST': 'dbmaster', # ... plus some other settings }, 'slave': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'myproject', 'HOST': 'dbslave', 'TEST_MIRROR': 'default' # ... plus some other settings } } In this setup, we have two database servers: ``dbmaster``, described by the database alias ``default``, and ``dbslave`` described by the alias ``slave``. As you might expect, ``dbslave`` has been configured by the database administrator as a read slave of ``dbmaster``, so in normal activity, any write to ``default`` will appear on ``slave``. If Django created two independent test databases, this would break any tests that expected replication to occur. However, the ``slave`` database has been configured as a test mirror (using the :setting:`TEST_MIRROR` setting), indicating that under testing, ``slave`` should be treated as a mirror of ``default``. When the test environment is configured, a test version of ``slave`` will *not* be created. Instead the connection to ``slave`` will be redirected to point at ``default``. As a result, writes to ``default`` will appear on ``slave`` -- but because they are actually the same database, not because there is data replication between the two databases. Other test conditions --------------------- Loading Loading @@ -1349,7 +1401,9 @@ set up, execute and tear down the test suite. Creates the test databases. Returns the list of old database names that will need to be restored Returns a data structure that provides enough detail to undo the changes that have been made. This data will be provided to the ``teardown_databases()`` function at the conclusion of testing. .. method:: DjangoTestSuiteRunner.run_suite(suite) Loading @@ -1357,9 +1411,13 @@ set up, execute and tear down the test suite. Returns the result produced by the running the test suite. .. method:: DjangoTestSuiteRunner.teardown_databases(old_names) .. method:: DjangoTestSuiteRunner.teardown_databases(old_config) Destroys the test databases, restoring pre-test conditions. Destroys the test databases, restoring the old names. ``old_config`` is a data structure defining the changes in the database configuration that need to be reversed. It is the return value of the ``setup_databases()`` method. .. method:: DjangoTestSuiteRunner.teardown_test_environment() Loading