|
| 1 | +""" |
| 2 | +Tests of edx_django_utils.db.queryset_utils. |
| 3 | +""" |
| 4 | +from ddt import data, ddt, unpack |
| 5 | +from django.contrib import auth |
| 6 | +from django.test import TestCase |
| 7 | + |
| 8 | +from edx_django_utils.db.queryset_utils import chunked_queryset |
| 9 | + |
| 10 | +User = auth.get_user_model() |
| 11 | + |
| 12 | + |
| 13 | +@ddt |
| 14 | +class TestQuerysetUtils(TestCase): |
| 15 | + """ |
| 16 | + Tests of edx_django_utils.db.queryset_utils. |
| 17 | + """ |
| 18 | + @unpack |
| 19 | + @data( |
| 20 | + (30, 10, [10, 10, 10]), |
| 21 | + (31, 10, [10, 10, 10, 1]), |
| 22 | + (10, 10, [10]), |
| 23 | + (7, 10, [7]), |
| 24 | + (0, 10, [0]), |
| 25 | + ) |
| 26 | + def test_chunked_queryset(self, query_size, chunk_size, expected_batches): |
| 27 | + User.objects.all().delete() |
| 28 | + |
| 29 | + # create objects size of query_size |
| 30 | + for number in range(query_size): |
| 31 | + User.objects.create(username="username_{number}".format(number=number)) |
| 32 | + |
| 33 | + queryset = User.objects.all() |
| 34 | + |
| 35 | + self.assertEqual(queryset.count(), query_size) |
| 36 | + for (batch_num, chunked_query) in enumerate(chunked_queryset(queryset, chunk_size)): |
| 37 | + self.assertEqual(chunked_query.count(), expected_batches[batch_num]) |
| 38 | + |
| 39 | + def test_concurrent_update(self): |
| 40 | + """ |
| 41 | + Test concurrent database modification wouldn't skip records. |
| 42 | + """ |
| 43 | + User.objects.all().delete() |
| 44 | + |
| 45 | + # Create 14 objects. |
| 46 | + for number in range(14): |
| 47 | + User.objects.create(username="username_{number}".format(number=number)) |
| 48 | + |
| 49 | + queryset = User.objects.all() |
| 50 | + |
| 51 | + # Now create chunks of size 10. |
| 52 | + chunked_query = chunked_queryset(queryset, chunk_size=10) |
| 53 | + |
| 54 | + # As there a total 14 objects and chunk size is 10, Assert first chunk should contain 10 objects. |
| 55 | + first_chunk = next(chunked_query) |
| 56 | + self.assertEqual(first_chunk.count(), 10) |
| 57 | + |
| 58 | + # Lets create a new object while iterating over the chunked_queryset. |
| 59 | + User.objects.create(username="one-more-user") |
| 60 | + |
| 61 | + # As now there are total 15 objects, the second chunk should contain 5 objects instead of 4. |
| 62 | + # that implies concurrent database modification won't skip records in this process. |
| 63 | + second_chunk = next(chunked_query) |
| 64 | + self.assertEqual(second_chunk.count(), 5) |
0 commit comments