#36429: IntegrityError on contentype creation when using transactional test with
AND without serialized_rollback
-----------------------------+---------------------------------------------
Reporter: Julie Rymer | Type: Bug
Status: new | Component: Testing framework
Version: 5.2 | Severity: Normal
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-----------------------------+---------------------------------------------
Related to #23727
When using `TransactionTestCase`, if you use rollback emulation with
`serialized_rollback=True` for some test but **not all**, you'll get a db
error because of a duplicate on ContentType.
{{{
django.db.utils.IntegrityError: UNIQUE constraint failed:
django_content_type.app_label, django_content_type.model
Traceback (most recent call last):
File "[...]/site-packages/django/db/backends/base/creation.py", line
163, in deserialize_db_from_string
obj.save()
}}}
== Problem analysis
When using `serialized_rollback=True`, on test setup the content of the
database that was previously serialised will be applied.
On teardown, the data will be flushed and the post_migrate signal won't be
emitted because of `inhibit_post_migrate` argument.
When using `serialized_rollback=False` no database content is loaded on
setup and on teardown the database is flushed and post_migrate signal will
be emitted.
ContentType objects get created from a post_migrate handler. They also get
serialised from database content.
So, what happens if a test with `serialized_rollback=True` get run
**after** a test with `serialized_rollback=False`? You get an
IntegrityError because the ContentType object are loaded from
`connection._test_serialized_contents` after they already were created
from the post_migrate handler emitted when flushing.
I think this is what is happening, please correct me if my assumptions are
wrong.
== How to reproduce
Using the "Writing your first Django app" tutorial, you can reproduce by
adding the following tests to the polls app:
{{{
from django.test import TransactionTestCase
class QuestionModel1Tests(TransactionTestCase):
serialized_rollback = False
def test_was_published_recently_with_future_question(self):
self.assertTrue(True)
class QuestionModel2Tests(TransactionTestCase):
serialized_rollback = True
def test_was_published_recently_with_future_question(self):
self.assertTrue(True)
}}}
This error fully depends on the order of the test execution. If you don't
get the error the first time, just add some more tests alternating
`serialized_rollback` True and False until you get the error. you'll get
it as soon as a serialised rollback test execute after a non-serialised
one.
--
Ticket URL: <https://code.djangoproject.com/ticket/36429>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/django-updates/0107019732653fd6-70777aa9-91e1-43aa-b4f7-b008fab61ee2-000000%40eu-central-1.amazonses.com.