Django ORM and TestCase

41 views
Skip to first unread message

howie9393

unread,
Jun 29, 2017, 3:01:42 PM6/29/17
to Django users
I was wondering how django.test.TestCase and the ORM interact. If I create a databased backed object in a TestCase, the ORM can "see" the object when I query for it, as expected.


from django.test import TestCase
class MyTests(TestCase):
   
def test_where_is_my_obj(self):
       
MyObj.objects.create(...)
       
self.assert(MyObj.objects.count(), 1) # this is true as expected


But let's say I put a break point right before the assert statement. If I were to connect to the test database directly using let's say "mysql -u myuser -p test_database_that_django_made", the myobj table is empty. How does the ORM know about this uncommited object? And, how can I see this object in the database shell?

Note: I can get mysql shell to "see" myobj if I use TransactionTestCase instead (which proves that TestCase isn't committing?) but it's extremely slow compared to TestCase.

howie9393

unread,
Jun 29, 2017, 3:01:47 PM6/29/17
to Django users
I was wondering how django.test.TestCase and the ORM interact. If I create a databased backed object in a TestCase, the ORM can "see" the object when I query for it, as expected.


from django.test import TestCase
class MyTests(TestCase):
   
def test_where_is_my_obj(self):
       
MyObj.objects.create(...)
       
self.assert(MyObj.objects.count(), 1) # this is true as expected


But let's say I put a breakpoint right before the assert statement. If I were to connect to the test database directly using let's say "mysql -u myuser -p test_database_that_django_made", the tables are empty. The MyObj table has no rows. How does the ORM know about this uncommited object? And, how can I see this object in the database shell?

Note: I can get the mysql shell to "see" this object if I use TransactionTestCase instead of TestCase but TransactionTestCase is extremely slow. Also, I'm just like to know how Django "sees" this object in TestCase. Thanks!!

Jani Tiainen

unread,
Jun 29, 2017, 5:34:28 PM6/29/17
to django...@googlegroups.com
Hi,

In TestCase Django wraps all tests within transaction and makes commit and rollback as no-op.

So only code that is within transaction (your test) will see the data.

After test is finished a rollback is issued to remove all the data inserted to db.

And there is no way to read that data outside transaction since its never committed.


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/41694eab-8800-49af-9124-6e241208d40d%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

howie9393

unread,
Jul 6, 2017, 12:58:03 PM7/6/17
to Django users
Thanks for the reply! So how does the Django ORM see that uncommitted data in the database when we run the MyObj.objects.count()? 


On Thursday, June 29, 2017 at 2:34:28 PM UTC-7, Jani Tiainen wrote:
Hi,

In TestCase Django wraps all tests within transaction and makes commit and rollback as no-op.

So only code that is within transaction (your test) will see the data.

After test is finished a rollback is issued to remove all the data inserted to db.

And there is no way to read that data outside transaction since its never committed.

29.6.2017 22.01 "howie9393" <howard...@gmail.com> kirjoitti:
I was wondering how django.test.TestCase and the ORM interact. If I create a databased backed object in a TestCase, the ORM can "see" the object when I query for it, as expected.


from django.test import TestCase
class MyTests(TestCase):
   
def test_where_is_my_obj(self):
       
MyObj.objects.create(...)
       
self.assert(MyObj.objects.count(), 1) # this is true as expected


But let's say I put a breakpoint right before the assert statement. If I were to connect to the test database directly using let's say "mysql -u myuser -p test_database_that_django_made", the tables are empty. The MyObj table has no rows. How does the ORM know about this uncommited object? And, how can I see this object in the database shell?

Note: I can get the mysql shell to "see" this object if I use TransactionTestCase instead of TestCase but TransactionTestCase is extremely slow. Also, I'm just like to know how Django "sees" this object in TestCase. Thanks!!

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

Jani Tiainen

unread,
Jul 6, 2017, 5:39:56 PM7/6/17
to django...@googlegroups.com
Because there is open transaction and changed data is readable within that transaction. And since each test runs in own transaction ORM can see the changes within each test.

Transaction is like a (new) file in text editor. You can edit text and only you can see the edited text. Only if you save the file it will be possible that someone else can read that text and changes you made.

To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

howie9393

unread,
Jul 6, 2017, 7:20:26 PM7/6/17
to Django users
Ok got it. Thanks for all the help!
Reply all
Reply to author
Forward
0 new messages