Opened 2 years ago

Closed 2 years ago

#33256 closed Cleanup/optimization (fixed)

Some schema tests don't clean up their tables

Reported by: Tim Graham Owned by: Mohammad Ali Mehdizadeh
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: yes UI/UX: no

Description

Some test errors on a second consecutive run of ./tests/runtests.py --settings=test_postgres --parallel=1 --keepdb schema shows that some tests leave behind their tables. Attached is an initial patch for a couple of the cases.

======================================================================
ERROR: test_add_foreign_key_quoted_db_table (schema.tests.SchemaTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tim/code/django/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
psycopg2.errors.DuplicateTable: relation "table_author_double_quoted" already exists


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/tim/code/django/django/test/utils.py", line 437, in inner
    return func(*args, **kwargs)
  File "/home/tim/code/django/django/test/testcases.py", line 1305, in skip_wrapper
    return test_func(*args, **kwargs)
  File "/home/tim/code/django/tests/schema/tests.py", line 3229, in test_add_foreign_key_quoted_db_table
    editor.create_model(Author)
  File "/home/tim/code/django/django/db/backends/base/schema.py", line 355, in create_model
    self.execute(sql, params or None)
  File "/home/tim/code/django/django/db/backends/base/schema.py", line 151, in execute
    cursor.execute(sql, params)
  File "/home/tim/code/django/django/db/backends/utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/home/tim/code/django/django/db/backends/utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/tim/code/django/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/tim/code/django/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/tim/code/django/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
django.db.utils.ProgrammingError: relation "table_author_double_quoted" already exists


======================================================================
ERROR: test_add_foreign_object (schema.tests.SchemaTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tim/code/django/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
psycopg2.errors.DuplicateTable: relation "schema_bookforeignobj" already exists


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/tim/code/django/tests/schema/tests.py", line 3238, in test_add_foreign_object
    editor.create_model(BookForeignObj)
  File "/home/tim/code/django/django/db/backends/base/schema.py", line 355, in create_model
    self.execute(sql, params or None)
  File "/home/tim/code/django/django/db/backends/base/schema.py", line 151, in execute
    cursor.execute(sql, params)
  File "/home/tim/code/django/django/db/backends/utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/home/tim/code/django/django/db/backends/utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/tim/code/django/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/tim/code/django/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/tim/code/django/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
django.db.utils.ProgrammingError: relation "schema_bookforeignobj" already exists


======================================================================
ERROR: test_remove_db_index_doesnt_remove_custom_indexes (schema.tests.SchemaTests)
Changing db_index to False doesn't remove indexes from Meta.indexes.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tim/code/django/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
psycopg2.errors.DuplicateTable: relation "schema_authorwithindexedname" already exists


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/tim/code/django/tests/schema/tests.py", line 2659, in test_remove_db_index_doesnt_remove_custom_indexes
    editor.create_model(AuthorWithIndexedName)
  File "/home/tim/code/django/django/db/backends/base/schema.py", line 355, in create_model
    self.execute(sql, params or None)
  File "/home/tim/code/django/django/db/backends/base/schema.py", line 151, in execute
    cursor.execute(sql, params)
  File "/home/tim/code/django/django/db/backends/utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/home/tim/code/django/django/db/backends/utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/tim/code/django/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/tim/code/django/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/tim/code/django/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
django.db.utils.ProgrammingError: relation "schema_authorwithindexedname" already exists


======================================================================
ERROR: test_remove_field_unique_does_not_remove_meta_constraints (schema.tests.SchemaTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tim/code/django/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
psycopg2.errors.DuplicateTable: relation "schema_authorwithuniquename" already exists


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/tim/code/django/django/test/testcases.py", line 1305, in skip_wrapper
    return test_func(*args, **kwargs)
  File "/home/tim/code/django/tests/schema/tests.py", line 2057, in test_remove_field_unique_does_not_remove_meta_constraints
    editor.create_model(AuthorWithUniqueName)
  File "/home/tim/code/django/django/db/backends/base/schema.py", line 355, in create_model
    self.execute(sql, params or None)
  File "/home/tim/code/django/django/db/backends/base/schema.py", line 151, in execute
    cursor.execute(sql, params)
  File "/home/tim/code/django/django/db/backends/utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/home/tim/code/django/django/db/backends/utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/tim/code/django/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/tim/code/django/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/tim/code/django/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
django.db.utils.ProgrammingError: relation "schema_authorwithuniquename" already exists


======================================================================
ERROR: test_remove_index_together_does_not_remove_meta_indexes (schema.tests.SchemaTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tim/code/django/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
psycopg2.errors.DuplicateTable: relation "schema_authorwithindexednameandbirthday" already exists


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/tim/code/django/django/test/testcases.py", line 1305, in skip_wrapper
    return test_func(*args, **kwargs)
  File "/home/tim/code/django/tests/schema/tests.py", line 2554, in test_remove_index_together_does_not_remove_meta_indexes
    editor.create_model(AuthorWithIndexedNameAndBirthday)
  File "/home/tim/code/django/django/db/backends/base/schema.py", line 355, in create_model
    self.execute(sql, params or None)
  File "/home/tim/code/django/django/db/backends/base/schema.py", line 151, in execute
    cursor.execute(sql, params)
  File "/home/tim/code/django/django/db/backends/utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/home/tim/code/django/django/db/backends/utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/tim/code/django/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/tim/code/django/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/tim/code/django/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
django.db.utils.ProgrammingError: relation "schema_authorwithindexednameandbirthday" already exists


======================================================================
ERROR: test_remove_unique_together_does_not_remove_meta_constraints (schema.tests.SchemaTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tim/code/django/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
psycopg2.errors.DuplicateTable: relation "schema_authorwithuniquenameandbirthday" already exists


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/tim/code/django/django/test/testcases.py", line 1305, in skip_wrapper
    return test_func(*args, **kwargs)
  File "/home/tim/code/django/tests/schema/tests.py", line 2176, in test_remove_unique_together_does_not_remove_meta_constraints
    editor.create_model(AuthorWithUniqueNameAndBirthday)
  File "/home/tim/code/django/django/db/backends/base/schema.py", line 355, in create_model
    self.execute(sql, params or None)
  File "/home/tim/code/django/django/db/backends/base/schema.py", line 151, in execute
    cursor.execute(sql, params)
  File "/home/tim/code/django/django/db/backends/utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/home/tim/code/django/django/db/backends/utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/tim/code/django/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/tim/code/django/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/tim/code/django/django/db/backends/utils.py", line 82, in _execute
    return self.cursor.execute(sql)
django.db.utils.ProgrammingError: relation "schema_authorwithuniquenameandbirthday" already exists


======================================================================
ERROR: test_unique_name_quoting (schema.tests.SchemaTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tim/code/django/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
psycopg2.errors.DuplicateTable: relation "unique-table" already exists


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/tim/code/django/tests/schema/tests.py", line 1978, in test_unique_name_quoting
    editor.alter_db_table(TagUniqueRename, old_table_name, 'unique-table')
  File "/home/tim/code/django/django/db/backends/base/schema.py", line 474, in alter_db_table
    self.execute(self.sql_rename_table % {
  File "/home/tim/code/django/django/db/backends/base/schema.py", line 151, in execute
    cursor.execute(sql, params)
  File "/home/tim/code/django/django/db/backends/utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/home/tim/code/django/django/db/backends/utils.py", line 75, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/tim/code/django/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/tim/code/django/django/db/utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/tim/code/django/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: relation "unique-table" already exists

Attachments (1)

33256-init.diff (1.6 KB ) - added by Tim Graham 2 years ago.

Download all attachments as: .zip

Change History (22)

by Tim Graham, 2 years ago

Attachment: 33256-init.diff added

comment:1 by Mariusz Felisiak, 2 years ago

Triage Stage: UnreviewedAccepted

comment:2 by banani720, 2 years ago

Owner: changed from nobody to banani720
Status: newassigned

[]

comment:3 by banani720, 2 years ago

If I have not done all of the cases yet, but just want to check in to see if I am going about this the correct way, should I still submit a pr? I've added a try-finally clauses to a couple of the test cases that are mentioned in the error log. This is my first time contributing to an open-source and the tutorial isn't quite clear how I should handle a situation like this. Any guidance would be appreciated.

comment:4 by Mariusz Felisiak, 2 years ago

If I have not done all of the cases yet, but just want to check in to see if I am going about this the correct way, should I still submit a pr?

I don't think there is a need to submit PR at this stage. You should be able to run tests locally and check that all schema tests work:

./runtests.py --settings=test_postgres --parallel=1 --keepdb schema

I'd submit PR when all test pass.

in reply to:  4 ; comment:5 by Ayush Joshi, 2 years ago

Replying to Mariusz Felisiak:

If I have not done all of the cases yet, but just want to check in to see if I am going about this the correct way, should I still submit a pr?

I don't think there is a need to submit PR at this stage. You should be able to run tests locally and check that all schema tests work:

./runtests.py --settings=test_postgres --parallel=1 --keepdb schema

I'd submit PR when all test pass.

When I run this command I don't know why but I'm getting the following ModuleNotFoundError, could you please help?

Testing against Django installed in '/Python/django/django'
Traceback (most recent call last):
  File "./runtests.py", line 657, in <module>
    failures = django_tests(
  File "./runtests.py", line 348, in django_tests
    test_labels, state = setup_run_tests(verbosity, start_at, start_after, test_labels)
  File "./runtests.py", line 278, in setup_run_tests
    test_modules, state = setup_collect_tests(start_at, start_after, test_labels=test_labels)
  File "./runtests.py", line 193, in setup_collect_tests
    'INSTALLED_APPS': settings.INSTALLED_APPS,
  File "/Python/django/django/conf/__init__.py", line 89, in __getattr__
    self._setup(name)
  File "/Python/django/django/conf/__init__.py", line 76, in _setup
    self._wrapped = Settings(settings_module)
  File "/Python/django/django/conf/__init__.py", line 184, in __init__
    mod = importlib.import_module(self.SETTINGS_MODULE)
  File "/usr/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 973, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'test_postgres'

I found that there is a test_postgresql module but when I try to test it

./runtests.py --settings=dbshell.test_postgresql --parallel=1 --keepdb schema

it gives me the following error, could you please help?

Testing against Django installed in '/Python/django/django'
Traceback (most recent call last):
  File "/Python/django/django/utils/connection.py", line 58, in __getitem__
    return getattr(self._connections, alias)
  File "/Python/django/lib/python3.8/site-packages/asgiref/local.py", line 107, in __getattr__
    raise AttributeError(f"{self!r} object has no attribute {key!r}")
AttributeError: <asgiref.local.Local object at 0x7fd81f6d4880> object has no attribute 'default'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "./runtests.py", line 657, in <module>
    failures = django_tests(
  File "./runtests.py", line 348, in django_tests
    test_labels, state = setup_run_tests(verbosity, start_at, start_after, test_labels)
  File "./runtests.py", line 278, in setup_run_tests
    test_modules, state = setup_collect_tests(start_at, start_after, test_labels=test_labels)
  File "./runtests.py", line 193, in setup_collect_tests
    'INSTALLED_APPS': settings.INSTALLED_APPS,
  File "/Python/django/django/conf/__init__.py", line 89, in __getattr__
    self._setup(name)
  File "/Python/django/django/conf/__init__.py", line 76, in _setup
    self._wrapped = Settings(settings_module)
  File "/Python/django/django/conf/__init__.py", line 184, in __init__
    mod = importlib.import_module(self.SETTINGS_MODULE)
  File "/usr/lib/python3.8/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 848, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/Python/django/tests/dbshell/test_postgresql.py", line 13, in <module>
    class PostgreSqlDbshellCommandTestCase(SimpleTestCase):
  File "/Python/django/tests/dbshell/test_postgresql.py", line 140, in PostgreSqlDbshellCommandTestCase
    @skipUnless(connection.vendor == 'postgresql', 'Requires a PostgreSQL connection')
  File "/Python/django/django/utils/connection.py", line 15, in __getattr__
    return getattr(self._connections[self._alias], item)
  File "/Python/django/django/utils/connection.py", line 60, in __getitem__
    if alias not in self.settings:
  File "/Python/django/django/utils/functional.py", line 56, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/Python/django/django/utils/connection.py", line 45, in settings
    self._settings = self.configure_settings(self._settings)
  File "/Python/django/django/db/utils.py", line 144, in configure_settings
    databases = super().configure_settings(databases)
  File "/Python/django/django/utils/connection.py", line 50, in configure_settings
    settings = getattr(django_settings, self.settings_name)
  File "/Python/django/django/conf/__init__.py", line 89, in __getattr__
    self._setup(name)
  File "/Python/django/django/conf/__init__.py", line 76, in _setup
    self._wrapped = Settings(settings_module)
  File "/Python/django/django/conf/__init__.py", line 204, in __init__
    warnings.warn(
django.utils.deprecation.RemovedInDjango50Warning: The default value of USE_TZ will change from False to True in Django 5.0. Set USE_TZ to False in your project settings if you want to keep the current default behavior.
Last edited 2 years ago by Ayush Joshi (previous) (diff)

in reply to:  5 comment:6 by Mariusz Felisiak, 2 years ago

Replying to Ayush Joshi:

When I run this command I don't know why but I'm getting the following ModuleNotFoundError, could you please help?

--settings should be a path to your settings (see docs) not a test module. If you're having trouble understanding how Django works, see TicketClosingReasons/UseSupportChannels for ways to get help.

comment:7 by Mohammad Ali Mehdizadeh, 2 years ago

Can I work on this ticket please?

in reply to:  description comment:8 by Mohammad Ali Mehdizadeh, 2 years ago

I run the command but I can't produce errors, every thing works nice.

(django-venv) root@DESKTOP-N10114T:/mnt/d/mycode/django# ./tests/runtests.py --settings=test_postgres --parallel=1 --keepdb schema
Testing against Django installed in '/mnt/d/mycode/django/django'
Found 176 test(s).
Using existing test database for alias 'default'...
System check identified no issues (0 silenced).
.s................sss...s.ss.....s..ss.sss.s......ss.s......................s.............s.....................s..s....s...s.....................s.............s.....
.s...s...s
----------------------------------------------------------------------
Ran 176 tests in 11.057s

OK (skipped=28)
Preserving test database for alias 'default'...
Last edited 2 years ago by Tim Graham (previous) (diff)

comment:9 by Tim Graham, 2 years ago

Have you run the command a second time so that you're reusing an existing database?

comment:10 by Mohammad Ali Mehdizadeh, 2 years ago

Owner: changed from banani720 to Mohammad Ali Mehdizadeh

in reply to:  9 comment:11 by Mohammad Ali Mehdizadeh, 2 years ago

Replying to Tim Graham:

Have you run the command a second time so that you're reusing an existing database?

No, I use a new instance of postgres and I check the databases and remove test_ database each time.
But I can't produce errors.

comment:12 by Mohammad Ali Mehdizadeh, 2 years ago

This is my test_postgres.py file:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'USER': 'postgres_user',
        'PASSWORD': 'postgres_password',
        'HOST': 'postgres_host',
        'PORT': 'postgres_port',
    },
    'other': {
        'ENGINE': 'django.db.backends.postgresql',
        'USER': 'postgres_user',
        'PASSWORD': 'postgres_password',
        'HOST': 'postgres_host',
        'PORT': 'postgres_port',
    },
}

SECRET_KEY = "django_tests_secret_key"

# Use a fast hasher to speed up tests.
PASSWORD_HASHERS = [
    "django.contrib.auth.hashers.MD5PasswordHasher",
]

DEFAULT_AUTO_FIELD = "django.db.models.AutoField"

USE_TZ = False

comment:13 by Tim Graham, 2 years ago

The errors happen on a second consecutive test run (and don't remove the existing database between test runs).

in reply to:  13 comment:15 by Mohammad Ali Mehdizadeh, 2 years ago

Replying to Tim Graham:

Thank you for guidance, I create the same error.
So have you any idea how to solve this issue?

comment:16 by Tim Graham, 2 years ago

I attached an initial patch to this ticket. You should apply similar techniques to other tests.

in reply to:  16 comment:17 by Mohammad Ali Mehdizadeh, 2 years ago

Replying to Tim Graham:
Do you have any idea, how to write a test for this scenario.

comment:18 by Tim Graham, 2 years ago

You only need to fix the existing errors. No additional tests are needed.

comment:19 by Mohammad Ali Mehdizadeh, 2 years ago

Has patch: set

I create a PR https://github.com/django/django/pull/15528
feel free to feedback me

Version 0, edited 2 years ago by Mohammad Ali Mehdizadeh (next)

comment:20 by Mariusz Felisiak, 2 years ago

Patch needs improvement: set

comment:21 by Mariusz Felisiak, 2 years ago

Patch needs improvement: unset
Triage Stage: AcceptedReady for checkin

comment:22 by Mariusz Felisiak <felisiak.mariusz@…>, 2 years ago

Resolution: fixed
Status: assignedclosed

In 4b66a5e6:

Fixed #33256 -- Fixed schema test failures when using --keepdb.

Note: See TracTickets for help on using tickets.
Back to Top