Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Reorganized the database test settings

Change database test settings from "TEST_"-prefixed entries in the
database settings dictionary to setting in a dictionary that is itself
an entry "TEST" in the database settings.

Refs #21775

Thanks Josh Smeaton for review.
  • Loading branch information...
commit 41afae4ce906838fc87d63962104cfb47991f68b 1 parent add1584
Shai Berger shaib authored
4 django/db/backends/creation.py
View
@@ -391,8 +391,8 @@ def _get_test_db_name(self):
_create_test_db() and when no external munging is done with the 'NAME'
or 'TEST_NAME' settings.
"""
- if self.connection.settings_dict['TEST_NAME']:
- return self.connection.settings_dict['TEST_NAME']
+ if self.connection.settings_dict['TEST']['NAME']:
+ return self.connection.settings_dict['TEST']['NAME']
return TEST_DATABASE_PREFIX + self.connection.settings_dict['NAME']
def _create_test_db(self, verbosity, autoclobber):
9 django/db/backends/mysql/creation.py
View
@@ -34,10 +34,11 @@ class DatabaseCreation(BaseDatabaseCreation):
def sql_table_creation_suffix(self):
suffix = []
- if self.connection.settings_dict['TEST_CHARSET']:
- suffix.append('CHARACTER SET %s' % self.connection.settings_dict['TEST_CHARSET'])
- if self.connection.settings_dict['TEST_COLLATION']:
- suffix.append('COLLATE %s' % self.connection.settings_dict['TEST_COLLATION'])
+ test_settings = self.connection.settings_dict['TEST']
+ if test_settings['CHARSET']:
+ suffix.append('CHARACTER SET %s' % test_settings['CHARSET'])
+ if test_settings['COLLATION']:
+ suffix.append('COLLATE %s' % test_settings['COLLATION'])
return ' '.join(suffix)
def sql_for_inline_foreign_key_references(self, model, field, known_models, style):
62 django/db/backends/oracle/creation.py
View
@@ -119,7 +119,9 @@ def _create_test_db(self, verbosity=1, autoclobber=False):
real_settings = settings.DATABASES[self.connection.alias]
real_settings['SAVED_USER'] = self.connection.settings_dict['SAVED_USER'] = self.connection.settings_dict['USER']
real_settings['SAVED_PASSWORD'] = self.connection.settings_dict['SAVED_PASSWORD'] = self.connection.settings_dict['PASSWORD']
- real_settings['TEST_USER'] = real_settings['USER'] = self.connection.settings_dict['TEST_USER'] = self.connection.settings_dict['USER'] = TEST_USER
+ real_test_settings = real_settings['TEST']
+ test_settings = self.connection.settings_dict['TEST']
+ real_test_settings['USER'] = real_settings['USER'] = test_settings['USER'] = self.connection.settings_dict['USER'] = TEST_USER
real_settings['PASSWORD'] = self.connection.settings_dict['PASSWORD'] = TEST_PASSWD
return self.connection.settings_dict['NAME']
@@ -216,56 +218,40 @@ def _execute_statements(self, cursor, statements, parameters, verbosity):
sys.stderr.write("Failed (%s)\n" % (err))
raise
+ def _test_settings_get(self, key, default=None, prefixed=None):
+ """
+ Return a value from the test settings dict,
+ or a given default,
+ or a prefixed entry from the main settings dict
+ """
+ settings_dict = self.connection.settings_dict
+ val = settings_dict['TEST'].get(key, default)
+ if val is None:
+ val = TEST_DATABASE_PREFIX + settings_dict[prefixed]
+ return val
+
def _test_database_name(self):
- name = TEST_DATABASE_PREFIX + self.connection.settings_dict['NAME']
- try:
- if self.connection.settings_dict['TEST_NAME']:
- name = self.connection.settings_dict['TEST_NAME']
- except AttributeError:
- pass
- return name
+ return self._test_settings_get('NAME', prefixed='NAME')
def _test_database_create(self):
- return self.connection.settings_dict.get('TEST_CREATE', True)
+ return self._test_settings_get('CREATE_DB', default=True)
def _test_user_create(self):
- return self.connection.settings_dict.get('TEST_USER_CREATE', True)
+ return self._test_settings_get('CREATE_USER', default=True)
def _test_database_user(self):
- name = TEST_DATABASE_PREFIX + self.connection.settings_dict['USER']
- try:
- if self.connection.settings_dict['TEST_USER']:
- name = self.connection.settings_dict['TEST_USER']
- except KeyError:
- pass
- return name
+ return self._test_settings_get('USER', prefixed='USER')
def _test_database_passwd(self):
- name = PASSWORD
- try:
- if self.connection.settings_dict['TEST_PASSWD']:
- name = self.connection.settings_dict['TEST_PASSWD']
- except KeyError:
- pass
- return name
+ return self._test_settings_get('PASSWORD', default=PASSWORD)
def _test_database_tblspace(self):
- name = TEST_DATABASE_PREFIX + self.connection.settings_dict['NAME']
- try:
- if self.connection.settings_dict['TEST_TBLSPACE']:
- name = self.connection.settings_dict['TEST_TBLSPACE']
- except KeyError:
- pass
- return name
+ return self._test_settings_get('TBLSPACE', prefixed='NAME')
def _test_database_tblspace_tmp(self):
- name = TEST_DATABASE_PREFIX + self.connection.settings_dict['NAME'] + '_temp'
- try:
- if self.connection.settings_dict['TEST_TBLSPACE_TMP']:
- name = self.connection.settings_dict['TEST_TBLSPACE_TMP']
- except KeyError:
- pass
- return name
+ settings_dict = self.connection.settings_dict
+ return settings_dict['TEST'].get('TBLSPACE_TMP',
+ TEST_DATABASE_PREFIX + settings_dict['NAME'] + '_temp')
def _get_test_db_name(self):
"""
7 django/db/backends/postgresql_psycopg2/creation.py
View
@@ -39,9 +39,10 @@ class DatabaseCreation(BaseDatabaseCreation):
}
def sql_table_creation_suffix(self):
- assert self.connection.settings_dict['TEST_COLLATION'] is None, "PostgreSQL does not support collation setting at database creation time."
- if self.connection.settings_dict['TEST_CHARSET']:
- return "WITH ENCODING '%s'" % self.connection.settings_dict['TEST_CHARSET']
+ test_settings = self.connection.settings_dict['TEST']
+ assert test_settings['COLLATION'] is None, "PostgreSQL does not support collation setting at database creation time."
+ if test_settings['CHARSET']:
+ return "WITH ENCODING '%s'" % test_settings['CHARSET']
return ''
def sql_indexes_for_field(self, model, f, style):
4 django/db/backends/sqlite3/creation.py
View
@@ -47,7 +47,7 @@ def sql_remove_table_constraints(self, model, references_to_delete, style):
return []
def _get_test_db_name(self):
- test_database_name = self.connection.settings_dict['TEST_NAME']
+ test_database_name = self.connection.settings_dict['TEST']['NAME']
if test_database_name and test_database_name != ':memory:':
return test_database_name
return ':memory:'
@@ -83,7 +83,7 @@ def test_db_signature(self):
This takes into account the special cases of ":memory:" and "" for
SQLite since the databases will be distinct despite having the same
- TEST_NAME. See http://www.sqlite.org/inmemorydb.html
+ TEST NAME. See http://www.sqlite.org/inmemorydb.html
"""
test_dbname = self._get_test_db_name()
sig = [self.connection.settings_dict['NAME']]
38 django/db/utils.py
View
@@ -181,14 +181,48 @@ def ensure_defaults(self, alias):
conn.setdefault('TIME_ZONE', 'UTC' if settings.USE_TZ else settings.TIME_ZONE)
for setting in ['NAME', 'USER', 'PASSWORD', 'HOST', 'PORT']:
conn.setdefault(setting, '')
- for setting in ['TEST_CHARSET', 'TEST_COLLATION', 'TEST_NAME', 'TEST_MIRROR']:
- conn.setdefault(setting, None)
+
+ TEST_SETTING_RENAMES = {
+ 'CREATE': 'CREATE_DB',
+ 'USER_CREATE': 'CREATE_USER',
+ 'PASSWD': 'PASSWORD',
+ }
+
+ def prepare_test_settings(self, alias):
+ """
+ Makes sure the test settings are available in the 'TEST' sub-dictionary.
+ """
+ try:
+ conn = self.databases[alias]
+ except KeyError:
+ raise ConnectionDoesNotExist("The connection %s doesn't exist" % alias)
+
+ test_settings = conn.setdefault('TEST', {})
+ for key, value in six.iteritems(conn):
+ if key.startswith('TEST_'):
+ new_key = key[5:]
+ new_key = self.TEST_SETTING_RENAMES.get(new_key, new_key)
+ if new_key in test_settings:
+ raise ImproperlyConfigured("Connection %s has both %s and TEST[%s] specified." %
Tim Graham Owner

One issue here is that I cannot create a single settings file for the CI server that both silences the deprecation warning and is compatible with older version of Django. Would you consider relaxing the constraint to use TEST if defined, and ignore TEST_* in that case (no warnings for those values)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ (alias, key, new_key))
+ warnings.warn("In Django 1.9 the %s connection setting will be moved "
+ "to a %s entry in the TEST setting" % (key, new_key),
+ RemovedInDjango19Warning, stacklevel=2)
+ test_settings[new_key] = value
+ # Check that they didn't just use the old name with 'TEST_' removed
+ for key, new_key in six.iteritems(self.TEST_SETTING_RENAMES):
+ if key in test_settings:
+ warnings.warn("Test setting %s was renamed to %s; specified value (%s) ignored" %
+ (key, new_key, test_settings[key]), stacklevel=2)
+ for key in ['CHARSET', 'COLLATION', 'NAME', 'MIRROR']:
+ test_settings.setdefault(key, None)
def __getitem__(self, alias):
if hasattr(self._connections, alias):
return getattr(self._connections, alias)
self.ensure_defaults(alias)
+ self.prepare_test_settings(alias)
db = self.databases[alias]
backend = load_backend(db['ENGINE'])
conn = backend.DatabaseWrapper(db, alias)
18 django/test/runner.py
View
@@ -170,7 +170,7 @@ def is_discoverable(label):
def dependency_ordered(test_databases, dependencies):
"""
Reorder test_databases into an order that honors the dependencies
- described in TEST_DEPENDENCIES.
+ described in TEST[DEPENDENCIES].
"""
ordered_test_databases = []
resolved_databases = set()
@@ -204,7 +204,7 @@ def dependency_ordered(test_databases, dependencies):
if not changed:
raise ImproperlyConfigured(
- "Circular dependency in TEST_DEPENDENCIES")
+ "Circular dependency in TEST[DEPENDENCIES]")
test_databases = deferred
return ordered_test_databases
@@ -261,11 +261,11 @@ def setup_databases(verbosity, interactive, **kwargs):
default_sig = connections[DEFAULT_DB_ALIAS].creation.test_db_signature()
for alias in connections:
connection = connections[alias]
- if connection.settings_dict['TEST_MIRROR']:
+ 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] = (
- connection.settings_dict['TEST_MIRROR'])
+ 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,
@@ -276,13 +276,11 @@ def setup_databases(verbosity, interactive, **kwargs):
)
item[1].add(alias)
- if 'TEST_DEPENDENCIES' in connection.settings_dict:
- dependencies[alias] = (
- connection.settings_dict['TEST_DEPENDENCIES'])
+ 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] = connection.settings_dict.get(
- 'TEST_DEPENDENCIES', [DEFAULT_DB_ALIAS])
+ dependencies[alias] = test_settings.get('DEPENDENCIES', [DEFAULT_DB_ALIAS])
# Second pass -- actually create the databases.
old_names = []
2  django/test/testcases.py
View
@@ -762,7 +762,7 @@ def _databases_names(self, include_mirrors=True):
# including mirrors or not. Otherwise, just on the default DB.
if getattr(self, 'multi_db', False):
return [alias for alias in connections
- if include_mirrors or not connections[alias].settings_dict['TEST_MIRROR']]
+ if include_mirrors or not connections[alias].settings_dict['TEST']['MIRROR']]
else:
return [DEFAULT_DB_ALIAS]
3  docs/internals/deprecation.txt
View
@@ -121,6 +121,9 @@ details on these changes.
* ``django.utils.text.javascript_quote`` will be removed.
+* Database test settings as independent entries in the database settings,
+ prefixed by ``TEST_``, will no longer be supported.
+
.. _deprecation-removed-in-1.8:
1.8
204 docs/ref/settings.txt
View
@@ -605,10 +605,29 @@ Default: ``''`` (Empty string)
The username to use when connecting to the database. Not used with SQLite.
+.. setting:: DATABASE-TEST
+
+TEST
+~~~~
+
+.. versionchanged:: 1.7
+
+ All :setting:`TEST <DATABASE-TEST>` sub-entries used to be independent
+ entries in the database settings dictionary, with a ``TEST_`` prefix.
+ Further, ``TEST_CREATE``, ``TEST_USER_CREATE`` and ``TEST_PASSWD``
+ were changed to ``CREATE_DB``, ``CREATE_USER`` and ``PASSWORD``
+ respectively.
+
+Default: ``{}``
+
+A dictionary of settings for test databases; for more details about the
+creation and use of test databases, see :ref:`the-test-database`. The
+following entries are available:
+
.. setting:: TEST_CHARSET
-TEST_CHARSET
-~~~~~~~~~~~~
+CHARSET
+^^^^^^^
Default: ``None``
@@ -624,8 +643,8 @@ backends.
.. setting:: TEST_COLLATION
-TEST_COLLATION
-~~~~~~~~~~~~~~
+COLLATION
+^^^^^^^^^
Default: ``None``
@@ -638,8 +657,8 @@ Only supported for the ``mysql`` backend (see the `MySQL manual`_ for details).
.. setting:: TEST_DEPENDENCIES
-TEST_DEPENDENCIES
-~~~~~~~~~~~~~~~~~
+DEPENDENCIES
+^^^^^^^^^^^^
Default: ``['default']``, for all databases other than ``default``,
which has no dependencies.
@@ -650,8 +669,8 @@ on :ref:`controlling the creation order of test databases
.. setting:: TEST_MIRROR
-TEST_MIRROR
-~~~~~~~~~~~
+MIRROR
+^^^^^^
Default: ``None``
@@ -665,8 +684,8 @@ configurations of multiple databases. See the documentation on
.. setting:: TEST_NAME
-TEST_NAME
-~~~~~~~~~
+NAME
+^^^^
Default: ``None``
@@ -680,8 +699,8 @@ See :ref:`the-test-database`.
.. setting:: TEST_CREATE
-TEST_CREATE
-~~~~~~~~~~~
+CREATE_DB
+^^^^^^^^^
Default: ``True``
@@ -690,34 +709,34 @@ This is an Oracle-specific setting.
If it is set to ``False``, the test tablespaces won't be automatically created
at the beginning of the tests and dropped at the end.
-.. setting:: TEST_USER
+.. setting:: TEST_USER_CREATE
-TEST_USER
-~~~~~~~~~
+CREATE_USER
+^^^^^^^^^^^
-Default: ``None``
+Default: ``True``
This is an Oracle-specific setting.
-The username to use when connecting to the Oracle database that will be used
-when running tests. If not provided, Django will use ``'test_' + USER``.
+If it is set to ``False``, the test user won't be automatically created at the
+beginning of the tests and dropped at the end.
-.. setting:: TEST_USER_CREATE
+.. setting:: TEST_USER
-TEST_USER_CREATE
-~~~~~~~~~~~~~~~~
+USER
+^^^^
-Default: ``True``
+Default: ``None``
This is an Oracle-specific setting.
-If it is set to ``False``, the test user won't be automatically created at the
-beginning of the tests and dropped at the end.
+The username to use when connecting to the Oracle database that will be used
+when running tests. If not provided, Django will use ``'test_' + USER``.
.. setting:: TEST_PASSWD
-TEST_PASSWD
-~~~~~~~~~~~
+PASSWORD
+^^^^^^^^
Default: ``None``
@@ -728,8 +747,8 @@ when running tests. If not provided, Django will use a hardcoded default value.
.. setting:: TEST_TBLSPACE
-TEST_TBLSPACE
-~~~~~~~~~~~~~
+TBLSPACE
+^^^^^^^^
Default: ``None``
@@ -740,8 +759,8 @@ provided, Django will use ``'test_' + NAME``.
.. setting:: TEST_TBLSPACE_TMP
-TEST_TBLSPACE_TMP
-~~~~~~~~~~~~~~~~~
+TBLSPACE_TMP
+^^^^^^^^^^^^
Default: ``None``
@@ -750,6 +769,116 @@ This is an Oracle-specific setting.
The name of the temporary tablespace that will be used when running tests. If
not provided, Django will use ``'test_' + NAME + '_temp'``.
+.. setting:: OLD_TEST_CHARSET
+
+TEST_CHARSET
+~~~~~~~~~~~~
+
+.. deprecated:: 1.7
+
+ Use the :setting:`CHARSET <TEST_CHARSET>` entry in the
+ :setting:`TEST <DATABASE-TEST>` dictionary.
+
+.. setting:: OLD_TEST_COLLATION
+
+TEST_COLLATION
+~~~~~~~~~~~~~~
+
+.. deprecated:: 1.7
+
+ Use the :setting:`COLLATION <TEST_COLLATION>` entry in the
+ :setting:`TEST <DATABASE-TEST>` dictionary.
+
+.. setting:: OLD_TEST_DEPENDENCIES
+
+TEST_DEPENDENCIES
+~~~~~~~~~~~~~~~~~
+
+.. deprecated:: 1.7
+
+ Use the :setting:`DEPENDENCIES <TEST_DEPENDENCIES>` entry in the
+ :setting:`TEST <DATABASE-TEST>` dictionary.
+
+.. setting:: OLD_TEST_MIRROR
+
+TEST_MIRROR
+~~~~~~~~~~~
+
+.. deprecated:: 1.7
+
+ Use the :setting:`MIRROR <TEST_MIRROR>` entry in the
+ :setting:`TEST <DATABASE-TEST>` dictionary.
+
+.. setting:: OLD_TEST_NAME
+
+TEST_NAME
+~~~~~~~~~
+
+.. deprecated:: 1.7
+
+ Use the :setting:`NAME <TEST_NAME>` entry in the
+ :setting:`TEST <DATABASE-TEST>` dictionary.
+
+.. setting:: OLD_TEST_CREATE
+
+TEST_CREATE
+~~~~~~~~~~~
+
+.. deprecated:: 1.7
+
+ Use the :setting:`CREATE_DB <TEST_CREATE>` entry in the
+ :setting:`TEST <DATABASE-TEST>` dictionary.
+
+.. setting:: OLD_TEST_USER
+
+TEST_USER
+~~~~~~~~~
+
+.. deprecated:: 1.7
+
+ Use the :setting:`USER <TEST_USER>` entry in the
+ :setting:`TEST <DATABASE-TEST>` dictionary.
+
+.. setting:: OLD_TEST_USER_CREATE
+
+TEST_USER_CREATE
+~~~~~~~~~~~~~~~~
+
+.. deprecated:: 1.7
+
+ Use the :setting:`CREATE_USER <TEST_USER_CREATE>` entry in the
+ :setting:`TEST <DATABASE-TEST>` dictionary.
+
+.. setting:: OLD_TEST_PASSWD
+
+TEST_PASSWD
+~~~~~~~~~~~
+
+.. deprecated:: 1.7
+
+ Use the :setting:`PASSWORD <TEST_PASSWD>` entry in the
+ :setting:`TEST <DATABASE-TEST>` dictionary.
+
+.. setting:: OLD_TEST_TBLSPACE
+
+TEST_TBLSPACE
+~~~~~~~~~~~~~
+
+.. deprecated:: 1.7
+
+ Use the :setting:`TBLSPACE <TEST_TBLSPACE>` entry in the
+ :setting:`TEST <DATABASE-TEST>` dictionary.
+
+.. setting:: OLD_TEST_TBLSPACE_TMP
+
+TEST_TBLSPACE_TMP
+~~~~~~~~~~~~~~~~~
+
+.. deprecated:: 1.7
+
+ Use the :setting:`TBLSPACE_TMP <TEST_TBLSPACE_TMP>` entry in the
+ :setting:`TEST <DATABASE-TEST>` dictionary.
+
.. setting:: DATABASE_ROUTERS
DATABASE_ROUTERS
@@ -2960,20 +3089,7 @@ Templates
Testing
-------
-* Database
-
- * :setting:`TEST_CHARSET`
- * :setting:`TEST_COLLATION`
- * :setting:`TEST_DEPENDENCIES`
- * :setting:`TEST_MIRROR`
- * :setting:`TEST_NAME`
- * :setting:`TEST_CREATE`
- * :setting:`TEST_USER`
- * :setting:`TEST_USER_CREATE`
- * :setting:`TEST_PASSWD`
- * :setting:`TEST_TBLSPACE`
- * :setting:`TEST_TBLSPACE_TMP`
-
+* Database: :setting:`TEST <DATABASE-TEST>`
* :setting:`TEST_RUNNER`
URLs
9 docs/releases/1.7.txt
View
@@ -785,6 +785,9 @@ Tests
* The ``WSGIRequest`` instance generated by the test handler is now attached to
the :attr:`django.test.Response.wsgi_request` attribute.
+* The database settings for testing have been collected into a dictionary
+ named :setting:`TEST <DATABASE-TEST>`.
+
Validators
^^^^^^^^^^
@@ -1459,3 +1462,9 @@ a risk of introducing XSS vulnerabilities. Along with ``fix_ampersands``,
``fix_ampersands``.
As this is an accelerated deprecation, ``fix_ampersands`` and ``clean_html``
will be removed in Django 1.8.
+
+Reorganization of database test settings
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+All database settings with a `TEST_` prefix have been deprecated in favor of
+entries in a :setting:`TEST <DATABASE-TEST>` dictionary in the database
+settings. The old settings will be supported until Django 1.9.
Tim Graham

One issue here is that I cannot create a single settings file for the CI server that both silences the deprecation warning and is compatible with older version of Django. Would you consider relaxing the constraint to use TEST if defined, and ignore TEST_* in that case (no warnings for those values)?

Please sign in to comment.
Something went wrong with that request. Please try again.