#23727 closed Bug (fixed)
IntegrityError with TransactionTestCase and serialized_rollback=True
| Reported by: | Tim Court | Owned by: | Tommy Beadle |
|---|---|---|---|
| Component: | Testing framework | Version: | 1.7 |
| Severity: | Normal | Keywords: | |
| Cc: | khoobks, dpoirier@…, Louis-Dominique Dubeau | Triage Stage: | Accepted |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Using a TransactionTestCase with a sqlite database raises an IntegrityError in Django 1.7. This is the error I'm seeing:
Traceback (most recent call last):
File "/tmp/djangomigrate/venv/local/lib/python2.7/site-packages/django/test/testcases.py", line 182, in __call__
self._pre_setup()
File "/tmp/djangomigrate/venv/local/lib/python2.7/site-packages/django/test/testcases.py", line 754, in _pre_setup
self._fixture_setup()
File "/tmp/djangomigrate/venv/local/lib/python2.7/site-packages/django/test/testcases.py", line 797, in _fixture_setup
connections[db_name]._test_serialized_contents
File "/tmp/djangomigrate/venv/local/lib/python2.7/site-packages/django/db/backends/creation.py", line 428, in deserialize_db_from_string
obj.save()
File "/tmp/djangomigrate/venv/local/lib/python2.7/site-packages/django/core/serializers/base.py", line 173, in save
models.Model.save_base(self.object, using=using, raw=True)
File "/tmp/djangomigrate/venv/local/lib/python2.7/site-packages/django/db/models/base.py", line 618, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/tmp/djangomigrate/venv/local/lib/python2.7/site-packages/django/db/models/base.py", line 699, in _save_table
result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/tmp/djangomigrate/venv/local/lib/python2.7/site-packages/django/db/models/base.py", line 732, in _do_insert
using=using, raw=raw)
File "/tmp/djangomigrate/venv/local/lib/python2.7/site-packages/django/db/models/manager.py", line 92, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/tmp/djangomigrate/venv/local/lib/python2.7/site-packages/django/db/models/query.py", line 921, in _insert
return query.get_compiler(using=using).execute_sql(return_id)
File "/tmp/djangomigrate/venv/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 920, in execute_sql
cursor.execute(sql, params)
File "/tmp/djangomigrate/venv/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 65, in execute
return self.cursor.execute(sql, params)
File "/tmp/djangomigrate/venv/local/lib/python2.7/site-packages/django/db/utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/tmp/djangomigrate/venv/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 65, in execute
return self.cursor.execute(sql, params)
File "/tmp/djangomigrate/venv/local/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py", line 485, in execute
return Database.Cursor.execute(self, query, params)
IntegrityError: columns app_label, model are not unique
I can reproduce this behaviour using the default project template, created using startproject and startapp, and nothing more than a single TransactionTestCase with two tests and the serialized_rollback option.
Here is a minimal sample project that demonstrates the problem: https://github.com/tctimmeh/djangomigrate. Running manage.py test mtestapp results in the error above.
It looks like the django.contrib.contenttypes app has a post-migrate script that populates the content type table. However, using the serialized_rollback option to refresh any migrated data also inserts saved duplicates into the content type table, which results in this exception.
Change History (13)
comment:1 by , 11 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:3 by , 11 years ago
| Cc: | added |
|---|
comment:4 by , 11 years ago
| Cc: | added |
|---|
comment:5 by , 11 years ago
FYI, I see this with Postgres as well, so it doesn't appear to be SQLite specific.
comment:6 by , 11 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:7 by , 11 years ago
| Has patch: | set |
|---|
I had a look at the PR, but I'm not confident enough to commit it. Also, some documentation might be needed (the loss of the post_migrate signal in this scenario might be backwards incompatible for some users).
comment:8 by , 10 years ago
| Cc: | added |
|---|
comment:9 by , 10 years ago
| Needs tests: | set |
|---|
Added a comment with an idea about a test on the pull request.
comment:10 by , 10 years ago
| Summary: | IntegrityError with TransactionTestCase and sqlite → IntegrityError with TransactionTestCase and serialized_rollback=True |
|---|
comment:13 by , 10 years ago
I have seen that this patch has been applied to Django 1.9.x.
For previous Django versions, I guess we can resolve this problem by setting:
TEST_NON_SERIALIZED_APPS = ['django.contrib.contenttypes']
as proposed in StackOverflow issue http://stackoverflow.com/questions/29226869/django-transactiontestcase-with-rollback-emulation/35359897 by @se7entyse7en. Is it right ?
I realise that this is not a good workaround but as a temporary measure I found that the following works in my situation.
I subclassed the TransactionTestCase and added the following code.
The the overridden
_fixture_teardowndisables thepost_migratesignal handlers from executing and creating the problematic rows in the database. This allows theTransactionTestCaseto successfully reload the original database state. The handlers are then manually invoked in the overriden_fixture_setupin order to ensure that for subsequent tests, the ContentTypes, Sites and Permissions are available.