#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.

Reply via email to