Opened 5 years ago
Last modified 3 years ago
#31055 closed Bug
Omits test_ prefix from database name when running subset of tests — at Initial Version
Reported by: | Matthijs Kooijman | Owned by: | nobody |
---|---|---|---|
Component: | Testing framework | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Matthijs Kooijman | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
While debugging some test framework issues wrt mysql, I noticed a problem where the test runner would try to access the test database without prefixing test_
, leading to an access denied error (because my permissions are set up tightly).
What I suspect happens is that this subset of tests only uses the default
database, so only that one is set up by DisoveryRunner.setup_databases
. This is confirmed by using a debugger, which shows databases only contains 'default'. Then, it runs the check
management command, which looks at settings.DATABASES
, which still contains the settings for default
and other
. This in turn causes a connection to the other
database to be made, but since the name of that database is not modified by create_test_db, that still refers to the original name, and the connection fails.
To reproduce, I have a clean master (c33eb6dcd0c211f8f02b2976fe3b3463f0a54498), with the following tests/test_mysql.py
:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': 'localhost', 'USER': 'test_django', 'PASSWORD': 'XXX', # Django prepends test_ to this name... 'NAME': 'django_main', }, 'other': { 'ENGINE': 'django.db.backends.mysql', 'HOST': 'localhost', 'USER': 'test_django', 'PASSWORD': 'XXX', # Django prepends test_ to this name... 'NAME': 'django_other', } } SECRET_KEY = "django_tests_secret_key" # Use a fast hasher to speed up tests. PASSWORD_HASHERS = [ 'django.contrib.auth.hashers.MD5PasswordHasher', ]
Then inside tests
, I run:
./runtests.py --settings test_mysql --parallel 1 timezones
I think the --parallel 1
is not strictly needed, but might make things easier to debug. With the above, I get:
Creating test database for alias 'default'... Destroying test database for alias 'default'... Testing against Django installed in '/home/matthijs/docs/src/upstream/django/django' Traceback (most recent call last): File "/home/matthijs/docs/src/upstream/django/django/db/backends/base/base.py", line 220, in ensure_connection self.connect() File "/home/matthijs/docs/src/upstream/django/django/utils/asyncio.py", line 24, in inner return func(*args, **kwargs) File "/home/matthijs/docs/src/upstream/django/django/db/backends/base/base.py", line 197, in connect self.connection = self.get_new_connection(conn_params) File "/home/matthijs/docs/src/upstream/django/django/utils/asyncio.py", line 24, in inner return func(*args, **kwargs) File "/home/matthijs/docs/src/upstream/django/django/db/backends/mysql/base.py", line 233, in get_new_connection return Database.connect(**conn_params) File "/home/matthijs/docs/src/upstream/django/venv/lib/python3.7/site-packages/MySQLdb/__init__.py", line 84, in Connect return Connection(*args, **kwargs) File "/home/matthijs/docs/src/upstream/django/venv/lib/python3.7/site-packages/MySQLdb/connections.py", line 179, in __init__ super(Connection, self).__init__(*args, **kwargs2) MySQLdb._exceptions.OperationalError: (1044, "Access denied for user 'test_django'@'localhost' to database 'django_other'") The above exception was the direct cause of the following exception: Traceback (most recent call last): File "./runtests.py", line 566, in <module> options.start_at, options.start_after, options.pdb, File "./runtests.py", line 308, in django_tests extra_tests=extra_tests, File "/home/matthijs/docs/src/upstream/django/django/test/runner.py", line 687, in run_tests self.run_checks() File "/home/matthijs/docs/src/upstream/django/django/test/runner.py", line 625, in run_checks call_command('check', verbosity=self.verbosity) File "/home/matthijs/docs/src/upstream/django/django/core/management/__init__.py", line 168, in call_command return command.execute(*args, **defaults) File "/home/matthijs/docs/src/upstream/django/django/core/management/base.py", line 369, in execute output = self.handle(*args, **options) File "/home/matthijs/docs/src/upstream/django/django/core/management/commands/check.py", line 64, in handle fail_level=getattr(checks, options['fail_level']), File "/home/matthijs/docs/src/upstream/django/django/core/management/base.py", line 395, in check include_deployment_checks=include_deployment_checks, File "/home/matthijs/docs/src/upstream/django/django/core/management/base.py", line 382, in _run_checks return checks.run_checks(**kwargs) File "/home/matthijs/docs/src/upstream/django/django/core/checks/registry.py", line 72, in run_checks new_errors = check(app_configs=app_configs) File "/home/matthijs/docs/src/upstream/django/django/core/checks/model_checks.py", line 34, in check_all_models errors.extend(model.check(**kwargs)) File "/home/matthijs/docs/src/upstream/django/django/db/models/base.py", line 1276, in check *cls._check_constraints(), File "/home/matthijs/docs/src/upstream/django/django/db/models/base.py", line 1842, in _check_constraints connection.features.supports_table_check_constraints or File "/home/matthijs/docs/src/upstream/django/django/utils/functional.py", line 48, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "/home/matthijs/docs/src/upstream/django/django/db/backends/mysql/features.py", line 97, in supports_column_check_constraints if self.connection.mysql_is_mariadb: File "/home/matthijs/docs/src/upstream/django/django/utils/functional.py", line 48, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "/home/matthijs/docs/src/upstream/django/django/db/backends/mysql/base.py", line 364, in mysql_is_mariadb return 'mariadb' in self.mysql_server_info.lower() File "/home/matthijs/docs/src/upstream/django/django/utils/functional.py", line 48, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "/home/matthijs/docs/src/upstream/django/django/db/backends/mysql/base.py", line 351, in mysql_server_info with self.temporary_connection() as cursor: File "/usr/lib/python3.7/contextlib.py", line 112, in __enter__ return next(self.gen) File "/home/matthijs/docs/src/upstream/django/django/db/backends/base/base.py", line 604, in temporary_connection with self.cursor() as cursor: File "/home/matthijs/docs/src/upstream/django/django/utils/asyncio.py", line 24, in inner return func(*args, **kwargs) File "/home/matthijs/docs/src/upstream/django/django/db/backends/base/base.py", line 260, in cursor return self._cursor() File "/home/matthijs/docs/src/upstream/django/django/db/backends/base/base.py", line 236, in _cursor self.ensure_connection() File "/home/matthijs/docs/src/upstream/django/django/utils/asyncio.py", line 24, in inner return func(*args, **kwargs) File "/home/matthijs/docs/src/upstream/django/django/db/backends/base/base.py", line 220, in ensure_connection self.connect() File "/home/matthijs/docs/src/upstream/django/django/db/utils.py", line 90, in __exit__ raise dj_exc_value.with_traceback(traceback) from exc_value File "/home/matthijs/docs/src/upstream/django/django/db/backends/base/base.py", line 220, in ensure_connection self.connect() File "/home/matthijs/docs/src/upstream/django/django/utils/asyncio.py", line 24, in inner return func(*args, **kwargs) File "/home/matthijs/docs/src/upstream/django/django/db/backends/base/base.py", line 197, in connect self.connection = self.get_new_connection(conn_params) File "/home/matthijs/docs/src/upstream/django/django/utils/asyncio.py", line 24, in inner return func(*args, **kwargs) File "/home/matthijs/docs/src/upstream/django/django/db/backends/mysql/base.py", line 233, in get_new_connection return Database.connect(**conn_params) File "/home/matthijs/docs/src/upstream/django/venv/lib/python3.7/site-packages/MySQLdb/__init__.py", line 84, in Connect return Connection(*args, **kwargs) File "/home/matthijs/docs/src/upstream/django/venv/lib/python3.7/site-packages/MySQLdb/connections.py", line 179, in __init__ super(Connection, self).__init__(*args, **kwargs2) django.db.utils.OperationalError: (1044, "Access denied for user 'test_django'@'localhost' to database 'django_other'")
I am not quite familiar with this code, and this is already a distraction from a distraction from a distraction from the actual project I was working on, so I'm going to leave this here for others to fix :-)