diff --git a/django/test/testcases.py b/django/test/testcases.py index 05cce99c3aa..716eef5e42e 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -1040,11 +1040,29 @@ class TransactionTestCase(SimpleTestCase): allow_cascade=self.available_apps is not None, inhibit_post_migrate=inhibit_post_migrate) - def assertQuerysetEqual(self, qs, values, transform=repr, ordered=True, msg=None): - items = map(transform, qs) + def assertQuerysetEqual(self, qs, values, transform=None, ordered=True, msg=None): + values = list(values) + # RemovedInDjango41Warning. + if transform is None: + if ( + values and isinstance(values[0], str) and + qs and not isinstance(qs[0], str) + ): + # Transform qs using repr() if the first element of values is a + # string and the first element of qs is not (which would be the + # case if qs is a flattened values_list). + warnings.warn( + "In Django 4.1, repr() will not be called automatically " + "on a queryset when compared to string values. Set an " + "explicit 'transform' to silence this warning.", + category=RemovedInDjango41Warning, + ) + transform = repr + items = qs + if transform is not None: + items = map(transform, items) if not ordered: return self.assertEqual(Counter(items), Counter(values), msg=msg) - values = list(values) # For example qs.iterator() could be passed as qs, but it does not # have 'ordered' attribute. if len(values) > 1 and hasattr(qs, 'ordered') and not qs.ordered: diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index 46a1aaaee69..06ea0fbbc01 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -26,6 +26,9 @@ details on these changes. * The ``default_app_config`` module variable will be removed. +* ``TransactionTestCase.assertQuerysetEqual()` will no longer automatically + call ``repr()`` on a queryset when compared to string values. + .. _deprecation-removed-in-4.0: 4.0 diff --git a/docs/intro/tutorial05.txt b/docs/intro/tutorial05.txt index 046abb8124a..1ff868b1cb9 100644 --- a/docs/intro/tutorial05.txt +++ b/docs/intro/tutorial05.txt @@ -498,11 +498,11 @@ class: Questions with a pub_date in the past are displayed on the index page. """ - create_question(question_text="Past question.", days=-30) + question = create_question(question_text="Past question.", days=-30) response = self.client.get(reverse('polls:index')) self.assertQuerysetEqual( response.context['latest_question_list'], - [''] + [question], ) def test_future_question(self): @@ -520,24 +520,24 @@ class: Even if both past and future questions exist, only past questions are displayed. """ - create_question(question_text="Past question.", days=-30) + question = create_question(question_text="Past question.", days=-30) create_question(question_text="Future question.", days=30) response = self.client.get(reverse('polls:index')) self.assertQuerysetEqual( response.context['latest_question_list'], - [''] + [question], ) def test_two_past_questions(self): """ The questions index page may display multiple questions. """ - create_question(question_text="Past question 1.", days=-30) - create_question(question_text="Past question 2.", days=-5) + question1 = create_question(question_text="Past question 1.", days=-30) + question2 = create_question(question_text="Past question 2.", days=-5) response = self.client.get(reverse('polls:index')) self.assertQuerysetEqual( response.context['latest_question_list'], - ['', ''] + [question2, question1], ) diff --git a/docs/releases/3.2.txt b/docs/releases/3.2.txt index a460f96eef7..f542a4fee98 100644 --- a/docs/releases/3.2.txt +++ b/docs/releases/3.2.txt @@ -422,6 +422,11 @@ Tests ` in a list. This allows you to test such callbacks without using the slower :class:`.TransactionTestCase`. +* :meth:`.TransactionTestCase.assertQuerysetEqual` now supports direct + comparison against another queryset rather than being restricted to + comparison against a list of string representations of objects when using the + default value for the ``transform`` argument. + URLs ~~~~ @@ -615,3 +620,8 @@ Miscellaneous * The ``default_app_config`` application configuration variable is deprecated, due to the now automatic ``AppConfig`` discovery. See :ref:`whats-new-3.2` for more details. + +* Automatically calling ``repr()`` on a queryset in + ``TransactionTestCase.assertQuerysetEqual()``, when compared to string + values, is deprecated. If you need the previous behavior, explicitly set + ``transform`` to ``repr``. diff --git a/docs/topics/testing/tools.txt b/docs/topics/testing/tools.txt index 2d108736112..678eb260aab 100644 --- a/docs/topics/testing/tools.txt +++ b/docs/topics/testing/tools.txt @@ -1683,15 +1683,13 @@ your test suite. Output in case of error can be customized with the ``msg`` argument. -.. method:: TransactionTestCase.assertQuerysetEqual(qs, values, transform=repr, ordered=True, msg=None) +.. method:: TransactionTestCase.assertQuerysetEqual(qs, values, transform=None, ordered=True, msg=None) - Asserts that a queryset ``qs`` returns a particular list of values ``values``. + Asserts that a queryset ``qs`` matches a particular iterable of values + ``values``. - The comparison of the contents of ``qs`` and ``values`` is performed by - applying ``transform`` to ``qs``. By default, this means that the - ``repr()`` of each value in ``qs`` is compared to the ``values``. Any other - callable can be used if ``repr()`` doesn't provide a unique or helpful - comparison. + If ``transform`` is provided, ``values`` is compared to a list produced by + applying ``transform`` to each member of ``qs``. By default, the comparison is also ordering dependent. If ``qs`` doesn't provide an implicit ordering, you can set the ``ordered`` parameter to @@ -1702,6 +1700,21 @@ your test suite. Output in case of error can be customized with the ``msg`` argument. + .. versionchanged:: 3.2 + + The default value of ``transform`` argument was changed to ``None``. + + .. versionadded:: 3.2 + + Support for direct comparison between querysets was added. + + .. deprecated:: 3.2 + + If ``transform`` is not provided and ``values`` is a list of strings, + it's compared to a list produced by applying ``repr()`` to each member + of ``qs``. This behavior is deprecated and will be removed in Django + 4.1. If you need it, explicitly set ``transform`` to ``repr``. + .. method:: TransactionTestCase.assertNumQueries(num, func, *args, **kwargs) Asserts that when ``func`` is called with ``*args`` and ``**kwargs`` that diff --git a/tests/aggregation/tests.py b/tests/aggregation/tests.py index 62704c4bd27..43fd9dd0749 100644 --- a/tests/aggregation/tests.py +++ b/tests/aggregation/tests.py @@ -750,13 +750,13 @@ class AggregateTestCase(TestCase): number of authors. """ dates = Book.objects.annotate(num_authors=Count("authors")).dates('pubdate', 'year') - self.assertQuerysetEqual( + self.assertSequenceEqual( dates, [ - "datetime.date(1991, 1, 1)", - "datetime.date(1995, 1, 1)", - "datetime.date(2007, 1, 1)", - "datetime.date(2008, 1, 1)" - ] + datetime.date(1991, 1, 1), + datetime.date(1995, 1, 1), + datetime.date(2007, 1, 1), + datetime.date(2008, 1, 1), + ], ) def test_values_aggregation(self): diff --git a/tests/basic/tests.py b/tests/basic/tests.py index 173458f5ff8..43c7ccdfa66 100644 --- a/tests/basic/tests.py +++ b/tests/basic/tests.py @@ -161,13 +161,11 @@ class ModelTest(TestCase): Article(headline=headline, pub_date=some_pub_date).save() self.assertQuerysetEqual( Article.objects.all().order_by('headline'), - ["", - "", - "", - ""] + sorted(headlines), + transform=lambda a: a.headline, ) Article.objects.filter(headline__startswith='A').delete() - self.assertQuerysetEqual(Article.objects.all().order_by('headline'), [""]) + self.assertEqual(Article.objects.get().headline, 'Boring article') def test_not_equal_and_equal_operators_behave_as_expected_on_instances(self): some_pub_date = datetime(2014, 5, 16, 12, 1) @@ -208,17 +206,17 @@ class ModelTest(TestCase): def test_year_lookup_edge_case(self): # Edge-case test: A year lookup should retrieve all objects in # the given year, including Jan. 1 and Dec. 31. - Article.objects.create( + a11 = Article.objects.create( headline='Article 11', pub_date=datetime(2008, 1, 1), ) - Article.objects.create( + a12 = Article.objects.create( headline='Article 12', pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999), ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(pub_date__year=2008), - ["", ""] + [a11, a12], ) def test_unicode_data(self): @@ -442,7 +440,7 @@ class ModelLookupTest(TestCase): self.a.save() # Article.objects.all() returns all the articles in the database. - self.assertQuerysetEqual(Article.objects.all(), ['']) + self.assertSequenceEqual(Article.objects.all(), [self.a]) def test_rich_lookup(self): # Django provides a rich database lookup API. @@ -458,24 +456,24 @@ class ModelLookupTest(TestCase): self.assertEqual(Article.objects.get(id=self.a.id), self.a) self.assertEqual(Article.objects.get(headline='Swallow programs in Python'), self.a) - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(pub_date__year=2005), - [''], + [self.a], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(pub_date__year=2004), [], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(pub_date__year=2005, pub_date__month=7), - [''], + [self.a], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(pub_date__week_day=5), - [''], + [self.a], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(pub_date__week_day=6), [], ) @@ -499,7 +497,7 @@ class ModelLookupTest(TestCase): self.assertEqual(Article.objects.get(pk=self.a.id), self.a) # pk can be used as a shortcut for the primary key name in any query. - self.assertQuerysetEqual(Article.objects.filter(pk__in=[self.a.id]), [""]) + self.assertSequenceEqual(Article.objects.filter(pk__in=[self.a.id]), [self.a]) # Model instances of the same type and same ID are considered equal. a = Article.objects.get(pk=self.a.id) diff --git a/tests/custom_columns/tests.py b/tests/custom_columns/tests.py index 874b0240501..b389a7e02f7 100644 --- a/tests/custom_columns/tests.py +++ b/tests/custom_columns/tests.py @@ -78,15 +78,15 @@ class CustomColumnsTests(TestCase): ) def test_author_querying(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.all().order_by('last_name'), - ['', ''] + [self.a2, self.a1], ) def test_author_filtering(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.filter(first_name__exact='John'), - [''] + [self.a1], ) def test_author_get(self): @@ -111,15 +111,12 @@ class CustomColumnsTests(TestCase): getattr(a, 'last') def test_m2m_table(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( self.article.authors.all().order_by('last_name'), - ['', ''] + [self.a2, self.a1], ) - self.assertQuerysetEqual( - self.a1.article_set.all(), - [''] - ) - self.assertQuerysetEqual( + self.assertSequenceEqual(self.a1.article_set.all(), [self.article]) + self.assertSequenceEqual( self.article.authors.filter(last_name='Jones'), - [''] + [self.a2], ) diff --git a/tests/custom_lookups/tests.py b/tests/custom_lookups/tests.py index 14f95a241b5..1be4de790d3 100644 --- a/tests/custom_lookups/tests.py +++ b/tests/custom_lookups/tests.py @@ -308,17 +308,17 @@ class BilateralTransformTests(TestCase): def test_bilateral_upper(self): with register_lookup(models.CharField, UpperBilateralTransform): - Author.objects.bulk_create([ - Author(name='Doe'), - Author(name='doe'), - Author(name='Foo'), - ]) - self.assertQuerysetEqual( + author1 = Author.objects.create(name='Doe') + author2 = Author.objects.create(name='doe') + author3 = Author.objects.create(name='Foo') + self.assertCountEqual( Author.objects.filter(name__upper='doe'), - ["", ""], ordered=False) - self.assertQuerysetEqual( + [author1, author2], + ) + self.assertSequenceEqual( Author.objects.filter(name__upper__contains='f'), - [""], ordered=False) + [author3], + ) def test_bilateral_inner_qs(self): with register_lookup(models.CharField, UpperBilateralTransform): diff --git a/tests/datetimes/tests.py b/tests/datetimes/tests.py index 857293acb69..f42936b5576 100644 --- a/tests/datetimes/tests.py +++ b/tests/datetimes/tests.py @@ -134,33 +134,42 @@ class DateTimesTests(TestCase): for i, pub_date in enumerate(pub_dates): Article(pub_date=pub_date, title='title #{}'.format(i)).save() - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.datetimes('pub_date', 'year'), - ["datetime.datetime(2005, 1, 1, 0, 0)"]) - self.assertQuerysetEqual( + [datetime.datetime(2005, 1, 1, 0, 0)], + ) + self.assertSequenceEqual( Article.objects.datetimes('pub_date', 'month'), - ["datetime.datetime(2005, 7, 1, 0, 0)"]) - self.assertQuerysetEqual( + [datetime.datetime(2005, 7, 1, 0, 0)], + ) + self.assertSequenceEqual( Article.objects.datetimes('pub_date', 'week'), - ["datetime.datetime(2005, 7, 25, 0, 0)"]) - self.assertQuerysetEqual( - Article.objects.datetimes('pub_date', 'day'), - ["datetime.datetime(2005, 7, 28, 0, 0)", - "datetime.datetime(2005, 7, 29, 0, 0)", - "datetime.datetime(2005, 7, 30, 0, 0)", - "datetime.datetime(2005, 7, 31, 0, 0)"]) - self.assertQuerysetEqual( + [datetime.datetime(2005, 7, 25, 0, 0)], + ) + self.assertSequenceEqual(Article.objects.datetimes('pub_date', 'day'), [ + datetime.datetime(2005, 7, 28, 0, 0), + datetime.datetime(2005, 7, 29, 0, 0), + datetime.datetime(2005, 7, 30, 0, 0), + datetime.datetime(2005, 7, 31, 0, 0), + ]) + self.assertSequenceEqual( Article.objects.datetimes('pub_date', 'day', order='ASC'), - ["datetime.datetime(2005, 7, 28, 0, 0)", - "datetime.datetime(2005, 7, 29, 0, 0)", - "datetime.datetime(2005, 7, 30, 0, 0)", - "datetime.datetime(2005, 7, 31, 0, 0)"]) - self.assertQuerysetEqual( + [ + datetime.datetime(2005, 7, 28, 0, 0), + datetime.datetime(2005, 7, 29, 0, 0), + datetime.datetime(2005, 7, 30, 0, 0), + datetime.datetime(2005, 7, 31, 0, 0), + ], + ) + self.assertSequenceEqual( Article.objects.datetimes('pub_date', 'day', order='DESC'), - ["datetime.datetime(2005, 7, 31, 0, 0)", - "datetime.datetime(2005, 7, 30, 0, 0)", - "datetime.datetime(2005, 7, 29, 0, 0)", - "datetime.datetime(2005, 7, 28, 0, 0)"]) + [ + datetime.datetime(2005, 7, 31, 0, 0), + datetime.datetime(2005, 7, 30, 0, 0), + datetime.datetime(2005, 7, 29, 0, 0), + datetime.datetime(2005, 7, 28, 0, 0), + ], + ) def test_datetimes_has_lazy_iterator(self): pub_dates = [ diff --git a/tests/distinct_on_fields/tests.py b/tests/distinct_on_fields/tests.py index e19c3c1b656..34d4509cecd 100644 --- a/tests/distinct_on_fields/tests.py +++ b/tests/distinct_on_fields/tests.py @@ -23,15 +23,15 @@ class DistinctOnTests(TestCase): cls.p3_o1 = Staff.objects.create(id=3, name="p3", organisation="o1") cls.p1_o2 = Staff.objects.create(id=4, name="p1", organisation="o2") cls.p1_o1.coworkers.add(cls.p2_o1, cls.p3_o1) - StaffTag.objects.create(staff=cls.p1_o1, tag=cls.t1) + cls.st1 = StaffTag.objects.create(staff=cls.p1_o1, tag=cls.t1) StaffTag.objects.create(staff=cls.p1_o1, tag=cls.t1) - celeb1 = Celebrity.objects.create(name="c1") - celeb2 = Celebrity.objects.create(name="c2") + cls.celeb1 = Celebrity.objects.create(name="c1") + cls.celeb2 = Celebrity.objects.create(name="c2") - cls.fan1 = Fan.objects.create(fan_of=celeb1) - cls.fan2 = Fan.objects.create(fan_of=celeb1) - cls.fan3 = Fan.objects.create(fan_of=celeb2) + cls.fan1 = Fan.objects.create(fan_of=cls.celeb1) + cls.fan2 = Fan.objects.create(fan_of=cls.celeb1) + cls.fan3 = Fan.objects.create(fan_of=cls.celeb2) def test_basic_distinct_on(self): """QuerySet.distinct('field', ...) works""" @@ -39,23 +39,23 @@ class DistinctOnTests(TestCase): qsets = ( ( Staff.objects.distinct().order_by('name'), - ['', '', '', ''], + [self.p1_o1, self.p1_o2, self.p2_o1, self.p3_o1], ), ( Staff.objects.distinct('name').order_by('name'), - ['', '', ''], + [self.p1_o1, self.p2_o1, self.p3_o1], ), ( Staff.objects.distinct('organisation').order_by('organisation', 'name'), - ['', ''], + [self.p1_o1, self.p1_o2], ), ( Staff.objects.distinct('name', 'organisation').order_by('name', 'organisation'), - ['', '', '', ''], + [self.p1_o1, self.p1_o2, self.p2_o1, self.p3_o1], ), ( Celebrity.objects.filter(fan__in=[self.fan1, self.fan2, self.fan3]).distinct('name').order_by('name'), - ['', ''], + [self.celeb1, self.celeb2], ), # Does combining querysets work? ( @@ -63,31 +63,28 @@ class DistinctOnTests(TestCase): distinct('name').order_by('name') | Celebrity.objects.filter(fan__in=[self.fan3]). distinct('name').order_by('name')), - ['', ''], - ), - ( - StaffTag.objects.distinct('staff', 'tag'), - [' p1>'], + [self.celeb1, self.celeb2], ), + (StaffTag.objects.distinct('staff', 'tag'), [self.st1]), ( Tag.objects.order_by('parent__pk', 'pk').distinct('parent'), - ['', '', ''] + [self.t2, self.t4, self.t1] if connection.features.nulls_order_largest - else ['', '', ''], + else [self.t1, self.t2, self.t4], ), ( StaffTag.objects.select_related('staff').distinct('staff__name').order_by('staff__name'), - [' p1>'], + [self.st1], ), # Fetch the alphabetically first coworker for each worker ( (Staff.objects.distinct('id').order_by('id', 'coworkers__name'). values_list('id', 'coworkers__name')), - ["(1, 'p2')", "(2, 'p1')", "(3, 'p1')", "(4, None)"] + [(1, 'p2'), (2, 'p1'), (3, 'p1'), (4, None)], ), ) for qset, expected in qsets: - self.assertQuerysetEqual(qset, expected) + self.assertSequenceEqual(qset, expected) self.assertEqual(qset.count(), len(expected)) # Combining queries with different distinct_fields is not allowed. diff --git a/tests/expressions/tests.py b/tests/expressions/tests.py index 2762dc3a1b1..8bcc7e4673b 100644 --- a/tests/expressions/tests.py +++ b/tests/expressions/tests.py @@ -70,9 +70,9 @@ class BasicExpressionsTests(TestCase): companies = Company.objects.annotate( foo=RawSQL('%s', ['value']), ).filter(foo='value').order_by('name') - self.assertQuerysetEqual( + self.assertSequenceEqual( companies, - ['', '', ''], + [self.example_inc, self.foobar_ltd, self.gmbh], ) def test_annotate_values_count(self): @@ -342,10 +342,10 @@ class BasicExpressionsTests(TestCase): def test_ticket_11722_iexact_lookup(self): Employee.objects.create(firstname="John", lastname="Doe") - Employee.objects.create(firstname="Test", lastname="test") + test = Employee.objects.create(firstname="Test", lastname="test") queryset = Employee.objects.filter(firstname__iexact=F('lastname')) - self.assertQuerysetEqual(queryset, [""]) + self.assertSequenceEqual(queryset, [test]) def test_ticket_16731_startswith_lookup(self): Employee.objects.create(firstname="John", lastname="Doe") @@ -810,44 +810,38 @@ class IterableLookupInnerExpressionsTests(TestCase): # MySQL requires that the values calculated for expressions don't pass # outside of the field's range, so it's inconvenient to use the values # in the more general tests. - Company.objects.create(name='5020 Ltd', num_employees=50, num_chairs=20, ceo=ceo) - Company.objects.create(name='5040 Ltd', num_employees=50, num_chairs=40, ceo=ceo) - Company.objects.create(name='5050 Ltd', num_employees=50, num_chairs=50, ceo=ceo) - Company.objects.create(name='5060 Ltd', num_employees=50, num_chairs=60, ceo=ceo) - cls.c5 = Company.objects.create(name='99300 Ltd', num_employees=99, num_chairs=300, ceo=ceo) + cls.c5020 = Company.objects.create(name='5020 Ltd', num_employees=50, num_chairs=20, ceo=ceo) + cls.c5040 = Company.objects.create(name='5040 Ltd', num_employees=50, num_chairs=40, ceo=ceo) + cls.c5050 = Company.objects.create(name='5050 Ltd', num_employees=50, num_chairs=50, ceo=ceo) + cls.c5060 = Company.objects.create(name='5060 Ltd', num_employees=50, num_chairs=60, ceo=ceo) + cls.c99300 = Company.objects.create(name='99300 Ltd', num_employees=99, num_chairs=300, ceo=ceo) def test_in_lookup_allows_F_expressions_and_expressions_for_integers(self): # __in lookups can use F() expressions for integers. queryset = Company.objects.filter(num_employees__in=([F('num_chairs') - 10])) - self.assertQuerysetEqual(queryset, [''], ordered=False) - self.assertQuerysetEqual( + self.assertSequenceEqual(queryset, [self.c5060]) + self.assertCountEqual( Company.objects.filter(num_employees__in=([F('num_chairs') - 10, F('num_chairs') + 10])), - ['', ''], - ordered=False + [self.c5040, self.c5060], ) - self.assertQuerysetEqual( + self.assertCountEqual( Company.objects.filter( num_employees__in=([F('num_chairs') - 10, F('num_chairs'), F('num_chairs') + 10]) ), - ['', '', ''], - ordered=False + [self.c5040, self.c5050, self.c5060], ) def test_expressions_in_lookups_join_choice(self): midpoint = datetime.time(13, 0) t1 = Time.objects.create(time=datetime.time(12, 0)) t2 = Time.objects.create(time=datetime.time(14, 0)) - SimulationRun.objects.create(start=t1, end=t2, midpoint=midpoint) + s1 = SimulationRun.objects.create(start=t1, end=t2, midpoint=midpoint) SimulationRun.objects.create(start=t1, end=None, midpoint=midpoint) SimulationRun.objects.create(start=None, end=t2, midpoint=midpoint) SimulationRun.objects.create(start=None, end=None, midpoint=midpoint) queryset = SimulationRun.objects.filter(midpoint__range=[F('start__time'), F('end__time')]) - self.assertQuerysetEqual( - queryset, - [''], - ordered=False - ) + self.assertSequenceEqual(queryset, [s1]) for alias in queryset.query.alias_map.values(): if isinstance(alias, Join): self.assertEqual(alias.join_type, constants.INNER) @@ -861,28 +855,21 @@ class IterableLookupInnerExpressionsTests(TestCase): def test_range_lookup_allows_F_expressions_and_expressions_for_integers(self): # Range lookups can use F() expressions for integers. Company.objects.filter(num_employees__exact=F("num_chairs")) - self.assertQuerysetEqual( + self.assertCountEqual( Company.objects.filter(num_employees__range=(F('num_chairs'), 100)), - ['', '', ''], - ordered=False + [self.c5020, self.c5040, self.c5050], ) - self.assertQuerysetEqual( + self.assertCountEqual( Company.objects.filter(num_employees__range=(F('num_chairs') - 10, F('num_chairs') + 10)), - ['', '', ''], - ordered=False + [self.c5040, self.c5050, self.c5060], ) - self.assertQuerysetEqual( + self.assertCountEqual( Company.objects.filter(num_employees__range=(F('num_chairs') - 10, 100)), - ['', '', '', ''], - ordered=False + [self.c5020, self.c5040, self.c5050, self.c5060], ) - self.assertQuerysetEqual( + self.assertCountEqual( Company.objects.filter(num_employees__range=(1, 100)), - [ - '', '', '', - '', '', - ], - ordered=False + [self.c5020, self.c5040, self.c5050, self.c5060, self.c99300], ) def test_range_lookup_namedtuple(self): @@ -890,7 +877,7 @@ class IterableLookupInnerExpressionsTests(TestCase): qs = Company.objects.filter( num_employees__range=EmployeeRange(minimum=51, maximum=100), ) - self.assertSequenceEqual(qs, [self.c5]) + self.assertSequenceEqual(qs, [self.c99300]) @unittest.skipUnless(connection.vendor == 'sqlite', "This defensive test only works on databases that don't validate parameter types") @@ -926,7 +913,7 @@ class IterableLookupInnerExpressionsTests(TestCase): completed=end.date(), estimated_time=end - start, ) - Result.objects.create( + r1 = Result.objects.create( experiment=experiment_1, result_time=datetime.datetime(2016, 2, 4, 15, 0, 0), ) @@ -941,11 +928,11 @@ class IterableLookupInnerExpressionsTests(TestCase): within_experiment_time = [F('experiment__start'), F('experiment__end')] queryset = Result.objects.filter(result_time__range=within_experiment_time) - self.assertQuerysetEqual(queryset, [""]) + self.assertSequenceEqual(queryset, [r1]) within_experiment_time = [F('experiment__start'), F('experiment__end')] queryset = Result.objects.filter(result_time__range=within_experiment_time) - self.assertQuerysetEqual(queryset, [""]) + self.assertSequenceEqual(queryset, [r1]) class FTests(SimpleTestCase): @@ -1005,30 +992,27 @@ class ExpressionsTests(TestCase): refs #16731 """ Employee.objects.bulk_create([ - Employee(firstname="%Joh\\nny", lastname="%Joh\\n"), Employee(firstname="Johnny", lastname="%John"), Employee(firstname="Jean-Claude", lastname="Claud_"), - Employee(firstname="Jean-Claude", lastname="Claude"), Employee(firstname="Jean-Claude", lastname="Claude%"), Employee(firstname="Johnny", lastname="Joh\\n"), - Employee(firstname="Johnny", lastname="John"), Employee(firstname="Johnny", lastname="_ohn"), ]) + claude = Employee.objects.create(firstname='Jean-Claude', lastname='Claude') + john = Employee.objects.create(firstname='Johnny', lastname='John') + john_sign = Employee.objects.create(firstname='%Joh\\nny', lastname='%Joh\\n') - self.assertQuerysetEqual( + self.assertCountEqual( Employee.objects.filter(firstname__contains=F('lastname')), - ["", "", ""], - ordered=False, + [john_sign, john, claude], ) - self.assertQuerysetEqual( + self.assertCountEqual( Employee.objects.filter(firstname__startswith=F('lastname')), - ["", ""], - ordered=False, + [john_sign, john], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Employee.objects.filter(firstname__endswith=F('lastname')), - [""], - ordered=False, + [claude], ) def test_insensitive_patterns_escape(self): @@ -1038,30 +1022,27 @@ class ExpressionsTests(TestCase): expression -- refs #16731 """ Employee.objects.bulk_create([ - Employee(firstname="%Joh\\nny", lastname="%joh\\n"), Employee(firstname="Johnny", lastname="%john"), Employee(firstname="Jean-Claude", lastname="claud_"), - Employee(firstname="Jean-Claude", lastname="claude"), Employee(firstname="Jean-Claude", lastname="claude%"), Employee(firstname="Johnny", lastname="joh\\n"), - Employee(firstname="Johnny", lastname="john"), Employee(firstname="Johnny", lastname="_ohn"), ]) + claude = Employee.objects.create(firstname='Jean-Claude', lastname='claude') + john = Employee.objects.create(firstname='Johnny', lastname='john') + john_sign = Employee.objects.create(firstname='%Joh\\nny', lastname='%joh\\n') - self.assertQuerysetEqual( + self.assertCountEqual( Employee.objects.filter(firstname__icontains=F('lastname')), - ["", "", ""], - ordered=False, + [john_sign, john, claude], ) - self.assertQuerysetEqual( + self.assertCountEqual( Employee.objects.filter(firstname__istartswith=F('lastname')), - ["", ""], - ordered=False, + [john_sign, john], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Employee.objects.filter(firstname__iendswith=F('lastname')), - [""], - ordered=False, + [claude], ) @@ -1126,7 +1107,8 @@ class ExpressionsNumericTests(TestCase): """ self.assertQuerysetEqual( Number.objects.all(), - ['', '', ''], + [(-1, -1), (42, 42), (1337, 1337)], + lambda n: (n.integer, round(n.float)), ordered=False ) @@ -1137,7 +1119,8 @@ class ExpressionsNumericTests(TestCase): self.assertEqual(Number.objects.filter(integer__gt=0).update(integer=F('integer') + 1), 2) self.assertQuerysetEqual( Number.objects.all(), - ['', '', ''], + [(-1, -1), (43, 42), (1338, 1337)], + lambda n: (n.integer, round(n.float)), ordered=False ) @@ -1149,7 +1132,8 @@ class ExpressionsNumericTests(TestCase): self.assertEqual(Number.objects.filter(integer__gt=0).update(integer=F('integer') + 1), 2) self.assertQuerysetEqual( Number.objects.exclude(float=F('integer')), - ['', ''], + [(43, 42), (1338, 1337)], + lambda n: (n.integer, round(n.float)), ordered=False ) @@ -1790,15 +1774,15 @@ class FieldTransformTests(TestCase): ) def test_transform_in_values(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Experiment.objects.values('assigned__month'), - ["{'assigned__month': 6}"] + [{'assigned__month': 6}], ) def test_multiple_transforms_in_values(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Experiment.objects.values('end__date__month'), - ["{'end__date__month': 6}"] + [{'end__date__month': 6}], ) diff --git a/tests/extra_regress/tests.py b/tests/extra_regress/tests.py index 01bedcbbeb3..d459ae6344d 100644 --- a/tests/extra_regress/tests.py +++ b/tests/extra_regress/tests.py @@ -118,8 +118,8 @@ class ExtraRegressTests(TestCase): extra() bits. """ qs = User.objects.all().extra(where=['id=%s'], params=[self.u.id]) - self.assertQuerysetEqual(qs, ['']) - self.assertQuerysetEqual(qs[:1], ['']) + self.assertSequenceEqual(qs, [self.u]) + self.assertSequenceEqual(qs[:1], [self.u]) def test_regression_8039(self): """ @@ -140,17 +140,17 @@ class ExtraRegressTests(TestCase): Regression test for #8819: Fields in the extra(select=...) list should be available to extra(order_by=...). """ - self.assertQuerysetEqual( + self.assertSequenceEqual( User.objects.filter(pk=self.u.id).extra(select={'extra_field': 1}).distinct(), - [''] + [self.u], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( User.objects.filter(pk=self.u.id).extra(select={'extra_field': 1}, order_by=['extra_field']), - [''] + [self.u], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( User.objects.filter(pk=self.u.id).extra(select={'extra_field': 1}, order_by=['extra_field']).distinct(), - [''] + [self.u], ) def test_dates_query(self): @@ -364,11 +364,11 @@ class ExtraRegressTests(TestCase): [{'pk': obj.pk}] ) - self.assertQuerysetEqual( + self.assertSequenceEqual( TestObject.objects.filter( pk__in=TestObject.objects.extra(select={'extra': 1}).values('pk') ), - [''] + [obj], ) self.assertEqual( @@ -376,16 +376,16 @@ class ExtraRegressTests(TestCase): [{'pk': obj.pk}] ) - self.assertQuerysetEqual( + self.assertSequenceEqual( TestObject.objects.filter( pk__in=TestObject.objects.values('pk').extra(select={'extra': 1}) ), - [''] + [obj], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( TestObject.objects.filter(pk=obj.pk) | TestObject.objects.extra(where=["id > %s"], params=[obj.pk]), - [''] + [obj], ) def test_regression_17877(self): @@ -394,11 +394,9 @@ class ExtraRegressTests(TestCase): contain OR operations. """ # Test Case 1: should appear in queryset. - t = TestObject(first='a', second='a', third='a') - t.save() + t1 = TestObject.objects.create(first='a', second='a', third='a') # Test Case 2: should appear in queryset. - t = TestObject(first='b', second='a', third='a') - t.save() + t2 = TestObject.objects.create(first='b', second='a', third='a') # Test Case 3: should not appear in queryset, bug case. t = TestObject(first='a', second='a', third='b') t.save() @@ -412,12 +410,11 @@ class ExtraRegressTests(TestCase): t = TestObject(first='a', second='b', third='b') t.save() - self.assertQuerysetEqual( + self.assertCountEqual( TestObject.objects.extra( where=["first = 'a' OR second = 'a'", "third = 'a'"], ), - ['', ''], - ordered=False + [t1, t2], ) def test_extra_values_distinct_ordering(self): diff --git a/tests/fixtures/tests.py b/tests/fixtures/tests.py index ac96c48734a..e0728445084 100644 --- a/tests/fixtures/tests.py +++ b/tests/fixtures/tests.py @@ -39,11 +39,13 @@ class TestCaseFixtureLoadingTests(TestCase): def test_class_fixtures(self): "Test case has installed 3 fixture objects" - self.assertQuerysetEqual(Article.objects.all(), [ - '', - '', - '', - ]) + self.assertSequenceEqual( + Article.objects.values_list('headline', flat=True), [ + 'Django conquers world!', + 'Copyright is fine the way it is', + 'Poker has no place on ESPN', + ], + ) class SubclassTestCaseFixtureLoadingTests(TestCaseFixtureLoadingTests): @@ -98,10 +100,10 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): Site.objects.all().delete() # Load fixture 1. Single JSON file, with two objects. management.call_command('loaddata', 'fixture1.json', verbosity=0) - self.assertQuerysetEqual(Article.objects.all(), [ - '', - '', - ]) + self.assertSequenceEqual( + Article.objects.values_list('headline', flat=True), + ['Time to reform copyright', 'Poker has no place on ESPN'], + ) # Dump the current contents of the database as a JSON fixture self._dumpdata_assert( @@ -184,27 +186,33 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): # Load fixture 2. JSON file imported by default. Overwrites some existing objects management.call_command('loaddata', 'fixture2.json', verbosity=0) - self.assertQuerysetEqual(Article.objects.all(), [ - '', - '', - '', - ]) + self.assertSequenceEqual( + Article.objects.values_list('headline', flat=True), + [ + 'Django conquers world!', + 'Copyright is fine the way it is', + 'Poker has no place on ESPN', + ], + ) # Load fixture 3, XML format. management.call_command('loaddata', 'fixture3.xml', verbosity=0) - self.assertQuerysetEqual(Article.objects.all(), [ - '', - '', - '', - '', - ]) + self.assertSequenceEqual( + Article.objects.values_list('headline', flat=True), + [ + 'XML identified as leading cause of cancer', + 'Django conquers world!', + 'Copyright is fine the way it is', + 'Poker on TV is great!', + ], + ) # Load fixture 6, JSON file with dynamic ContentType fields. Testing ManyToOne. management.call_command('loaddata', 'fixture6.json', verbosity=0) self.assertQuerysetEqual(Tag.objects.all(), [ ' tagged "copyright">', ' tagged "law">', - ], ordered=False) + ], transform=repr, ordered=False) # Load fixture 7, XML file with dynamic ContentType fields. Testing ManyToOne. management.call_command('loaddata', 'fixture7.xml', verbosity=0) @@ -213,7 +221,7 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): ' tagged "legal">', ' tagged "django">', ' tagged "world domination">', - ], ordered=False) + ], transform=repr, ordered=False) # Load fixture 8, JSON file with dynamic Permission fields. Testing ManyToMany. management.call_command('loaddata', 'fixture8.json', verbosity=0) @@ -221,7 +229,7 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): '', '', '' - ], ordered=False) + ], transform=repr, ordered=False) # Load fixture 9, XML file with dynamic Permission fields. Testing ManyToMany. management.call_command('loaddata', 'fixture9.xml', verbosity=0) @@ -229,15 +237,18 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): '', '', '' - ], ordered=False) + ], transform=repr, ordered=False) # object list is unaffected - self.assertQuerysetEqual(Article.objects.all(), [ - '', - '', - '', - '', - ]) + self.assertSequenceEqual( + Article.objects.values_list('headline', flat=True), + [ + 'XML identified as leading cause of cancer', + 'Django conquers world!', + 'Copyright is fine the way it is', + 'Poker on TV is great!', + ], + ) # By default, you get raw keys on dumpdata self._dumpdata_assert( @@ -390,13 +401,15 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): @unittest.skipIf(sys.platform == 'win32', "Windows doesn't support '?' in filenames.") def test_load_fixture_with_special_characters(self): management.call_command('loaddata', 'fixture_with[special]chars', verbosity=0) - self.assertQuerysetEqual(Article.objects.all(), ['']) + self.assertEqual( + Article.objects.get().headline, + 'How To Deal With Special Characters', + ) def test_dumpdata_with_filtering_manager(self): spy1 = Spy.objects.create(name='Paul') spy2 = Spy.objects.create(name='Alex', cover_blown=True) - self.assertQuerysetEqual(Spy.objects.all(), - ['']) + self.assertSequenceEqual(Spy.objects.all(), [spy1]) # Use the default manager self._dumpdata_assert( ['fixtures.Spy'], @@ -533,50 +546,54 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): def test_compress_format_loading(self): # Load fixture 4 (compressed), using format specification management.call_command('loaddata', 'fixture4.json', verbosity=0) - self.assertQuerysetEqual(Article.objects.all(), [ - '', - ]) + self.assertEqual(Article.objects.get().headline, 'Django pets kitten') def test_compressed_specified_loading(self): # Load fixture 5 (compressed), using format *and* compression specification management.call_command('loaddata', 'fixture5.json.zip', verbosity=0) - self.assertQuerysetEqual(Article.objects.all(), [ - '', - ]) + self.assertEqual( + Article.objects.get().headline, + 'WoW subscribers now outnumber readers', + ) def test_compressed_loading(self): # Load fixture 5 (compressed), only compression specification management.call_command('loaddata', 'fixture5.zip', verbosity=0) - self.assertQuerysetEqual(Article.objects.all(), [ - '', - ]) + self.assertEqual( + Article.objects.get().headline, + 'WoW subscribers now outnumber readers', + ) def test_compressed_loading_gzip(self): management.call_command('loaddata', 'fixture5.json.gz', verbosity=0) - self.assertQuerysetEqual(Article.objects.all(), [ - '', - ]) + self.assertEqual( + Article.objects.get().headline, + 'WoW subscribers now outnumber readers', + ) @unittest.skipUnless(HAS_BZ2, 'No bz2 library detected.') def test_compressed_loading_bz2(self): management.call_command('loaddata', 'fixture5.json.bz2', verbosity=0) - self.assertQuerysetEqual(Article.objects.all(), [ - '', - ]) + self.assertEqual( + Article.objects.get().headline, + 'WoW subscribers now outnumber readers', + ) @unittest.skipUnless(HAS_LZMA, 'No lzma library detected.') def test_compressed_loading_lzma(self): management.call_command('loaddata', 'fixture5.json.lzma', verbosity=0) - self.assertQuerysetEqual(Article.objects.all(), [ - '', - ]) + self.assertEqual( + Article.objects.get().headline, + 'WoW subscribers now outnumber readers', + ) @unittest.skipUnless(HAS_LZMA, 'No lzma library detected.') def test_compressed_loading_xz(self): management.call_command('loaddata', 'fixture5.json.xz', verbosity=0) - self.assertQuerysetEqual(Article.objects.all(), [ - '', - ]) + self.assertEqual( + Article.objects.get().headline, + 'WoW subscribers now outnumber readers', + ) def test_ambiguous_compressed_fixture(self): # The name "fixture5" is ambiguous, so loading raises an error. @@ -588,10 +605,13 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): # Load db fixtures 1 and 2. These will load using the 'default' database identifier implicitly management.call_command('loaddata', 'db_fixture_1', verbosity=0) management.call_command('loaddata', 'db_fixture_2', verbosity=0) - self.assertQuerysetEqual(Article.objects.all(), [ - '', - '', - ]) + self.assertSequenceEqual( + Article.objects.values_list('headline', flat=True), + [ + 'Who needs more than one database?', + 'Who needs to use compressed data?', + ], + ) def test_loaddata_error_message(self): """ @@ -622,9 +642,10 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): management.call_command('loaddata', 'db_fixture_1', verbosity=0, app_label="someotherapp") self.assertQuerysetEqual(Article.objects.all(), []) management.call_command('loaddata', 'db_fixture_1', verbosity=0, app_label="fixtures") - self.assertQuerysetEqual(Article.objects.all(), [ - '', - ]) + self.assertEqual( + Article.objects.get().headline, + 'Who needs more than one database?', + ) def test_loaddata_verbosity_three(self): output = StringIO() @@ -640,10 +661,13 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): # Load db fixtures 1 and 2. These will load using the 'default' database identifier explicitly management.call_command('loaddata', 'db_fixture_1', verbosity=0, database='default') management.call_command('loaddata', 'db_fixture_2', verbosity=0, database='default') - self.assertQuerysetEqual(Article.objects.all(), [ - '', - '', - ]) + self.assertSequenceEqual( + Article.objects.values_list('headline', flat=True), + [ + 'Who needs more than one database?', + 'Who needs to use compressed data?', + ], + ) def test_unmatched_identifier_loading(self): # Try to load db fixture 3. This won't load because the database identifier doesn't match @@ -662,7 +686,7 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): self.assertQuerysetEqual(Tag.objects.all(), [ ' tagged "copyright">', ' tagged "law">' - ], ordered=False) + ], transform=repr, ordered=False) # Dump the current contents of the database as a JSON fixture self._dumpdata_assert( @@ -707,14 +731,14 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): management.call_command('loaddata', 'fixture1', exclude=['fixtures'], verbosity=0) self.assertFalse(Article.objects.exists()) self.assertFalse(Category.objects.exists()) - self.assertQuerysetEqual(Site.objects.all(), ['']) + self.assertEqual(Site.objects.get().domain, 'example.com') def test_loading_with_exclude_model(self): Site.objects.all().delete() management.call_command('loaddata', 'fixture1', exclude=['fixtures.Article'], verbosity=0) self.assertFalse(Article.objects.exists()) - self.assertQuerysetEqual(Category.objects.all(), ['']) - self.assertQuerysetEqual(Site.objects.all(), ['']) + self.assertEqual(Category.objects.get().title, 'News Stories') + self.assertEqual(Site.objects.get().domain, 'example.com') def test_exclude_option_errors(self): """Excluding a bogus app or model should raise an error.""" @@ -740,18 +764,21 @@ class FixtureLoadingTests(DumpDataAssertMixin, TestCase): with mock.patch('django.core.management.commands.loaddata.sys.stdin', open(fixture_json)): management.call_command('loaddata', '--format=json', '-', verbosity=0) - self.assertQuerysetEqual(Article.objects.all(), [ - '', - '', - ]) + self.assertSequenceEqual( + Article.objects.values_list('headline', flat=True), + ['Time to reform copyright', 'Poker has no place on ESPN'], + ) with mock.patch('django.core.management.commands.loaddata.sys.stdin', open(fixture_xml)): management.call_command('loaddata', '--format=xml', '-', verbosity=0) - self.assertQuerysetEqual(Article.objects.all(), [ - '', - '', - '', - ]) + self.assertSequenceEqual( + Article.objects.values_list('headline', flat=True), + [ + 'XML identified as leading cause of cancer', + 'Time to reform copyright', + 'Poker on TV is great!', + ], + ) class NonexistentFixtureTests(TestCase): @@ -789,10 +816,10 @@ class FixtureTransactionTests(DumpDataAssertMixin, TransactionTestCase): def test_format_discovery(self): # Load fixture 1 again, using format discovery management.call_command('loaddata', 'fixture1', verbosity=0) - self.assertQuerysetEqual(Article.objects.all(), [ - '', - '', - ]) + self.assertSequenceEqual( + Article.objects.values_list('headline', flat=True), + ['Time to reform copyright', 'Poker has no place on ESPN'], + ) # Try to load fixture 2 using format discovery; this will fail # because there are two fixture2's in the fixtures directory @@ -801,10 +828,10 @@ class FixtureTransactionTests(DumpDataAssertMixin, TransactionTestCase): management.call_command('loaddata', 'fixture2', verbosity=0) # object list is unaffected - self.assertQuerysetEqual(Article.objects.all(), [ - '', - '', - ]) + self.assertSequenceEqual( + Article.objects.values_list('headline', flat=True), + ['Time to reform copyright', 'Poker has no place on ESPN'], + ) # Dump the current contents of the database as a JSON fixture self._dumpdata_assert( @@ -817,11 +844,14 @@ class FixtureTransactionTests(DumpDataAssertMixin, TransactionTestCase): # Load fixture 4 (compressed), using format discovery management.call_command('loaddata', 'fixture4', verbosity=0) - self.assertQuerysetEqual(Article.objects.all(), [ - '', - '', - '', - ]) + self.assertSequenceEqual( + Article.objects.values_list('headline', flat=True), + [ + 'Django pets kitten', + 'Time to reform copyright', + 'Poker has no place on ESPN', + ], + ) class ForwardReferenceTests(DumpDataAssertMixin, TestCase): @@ -861,9 +891,9 @@ class ForwardReferenceTests(DumpDataAssertMixin, TestCase): management.call_command('loaddata', 'forward_reference_m2m.json', verbosity=0) self.assertEqual(NaturalKeyThing.objects.count(), 3) t1 = NaturalKeyThing.objects.get_by_natural_key('t1') - self.assertQuerysetEqual( - t1.other_things.order_by('key'), - ['', ''] + self.assertSequenceEqual( + t1.other_things.order_by('key').values_list('key', flat=True), + ['t2', 't3'], ) self._dumpdata_assert( ['fixtures'], @@ -883,9 +913,9 @@ class ForwardReferenceTests(DumpDataAssertMixin, TestCase): ) self.assertEqual(NaturalKeyThing.objects.count(), 3) t1 = NaturalKeyThing.objects.get_by_natural_key('t1') - self.assertQuerysetEqual( - t1.other_things.order_by('key'), - ['', ''] + self.assertSequenceEqual( + t1.other_things.order_by('key').values_list('key', flat=True), + ['t2', 't3'], ) self._dumpdata_assert( ['fixtures'], diff --git a/tests/fixtures_regress/tests.py b/tests/fixtures_regress/tests.py index cc4cee3de42..4a22dc02469 100644 --- a/tests/fixtures_regress/tests.py +++ b/tests/fixtures_regress/tests.py @@ -747,7 +747,8 @@ class NaturalKeyFixtureTests(TestCase): "", "", "", - ] + ], + transform=repr, ) @@ -845,10 +846,7 @@ class M2MNaturalKeyFixtureTests(TestCase): obj.save() new_a = M2MSimpleA.objects.get_by_natural_key("a") - self.assertQuerysetEqual(new_a.b_set.all(), [ - "", - "" - ], ordered=False) + self.assertCountEqual(new_a.b_set.all(), [b1, b2]) class TestTicket11101(TransactionTestCase): diff --git a/tests/foreign_object/tests.py b/tests/foreign_object/tests.py index a33f29a38c3..2473a0a732a 100644 --- a/tests/foreign_object/tests.py +++ b/tests/foreign_object/tests.py @@ -408,15 +408,15 @@ class MultiColumnFKTests(TestCase): Person.objects.bulk_create(objs, 10) def test_isnull_lookup(self): - Membership.objects.create(membership_country=self.usa, person=self.bob, group_id=None) - Membership.objects.create(membership_country=self.usa, person=self.bob, group=self.cia) - self.assertQuerysetEqual( + m1 = Membership.objects.create(membership_country=self.usa, person=self.bob, group_id=None) + m2 = Membership.objects.create(membership_country=self.usa, person=self.bob, group=self.cia) + self.assertSequenceEqual( Membership.objects.filter(group__isnull=True), - [''] + [m1], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Membership.objects.filter(group__isnull=False), - [''] + [m2], ) diff --git a/tests/generic_relations/tests.py b/tests/generic_relations/tests.py index 0eb9dee03b4..2402f3d031b 100644 --- a/tests/generic_relations/tests.py +++ b/tests/generic_relations/tests.py @@ -25,10 +25,10 @@ class GenericRelationsTests(TestCase): cls.quartz = Mineral.objects.create(name='Quartz', hardness=7) # Tagging stuff. - cls.bacon.tags.create(tag='fatty') - cls.bacon.tags.create(tag='salty') - cls.lion.tags.create(tag='yellow') - cls.lion.tags.create(tag='hairy') + cls.fatty = cls.bacon.tags.create(tag='fatty') + cls.salty = cls.bacon.tags.create(tag='salty') + cls.yellow = cls.lion.tags.create(tag='yellow') + cls.hairy = cls.lion.tags.create(tag='hairy') def comp_func(self, obj): # Original list of tags: @@ -86,14 +86,8 @@ class GenericRelationsTests(TestCase): Objects with declared GenericRelations can be tagged directly -- the API mimics the many-to-many API. """ - self.assertQuerysetEqual(self.lion.tags.all(), [ - "", - "" - ]) - self.assertQuerysetEqual(self.bacon.tags.all(), [ - "", - "" - ]) + self.assertSequenceEqual(self.lion.tags.all(), [self.hairy, self.yellow]) + self.assertSequenceEqual(self.bacon.tags.all(), [self.fatty, self.salty]) def test_access_content_object(self): """ @@ -105,9 +99,7 @@ class GenericRelationsTests(TestCase): def test_query_content_object(self): qs = TaggedItem.objects.filter( animal__isnull=False).order_by('animal__common_name', 'tag') - self.assertQuerysetEqual( - qs, ["", ""] - ) + self.assertSequenceEqual(qs, [self.hairy, self.yellow]) mpk = ManualPK.objects.create(id=1) mpk.tags.create(tag='mpk') @@ -124,17 +116,14 @@ class GenericRelationsTests(TestCase): # defined. That's OK, because you can create TaggedItems explicitly. # However, excluding GenericRelations means your lookups have to be a # bit more explicit. - TaggedItem.objects.create(content_object=self.quartz, tag="shiny") - TaggedItem.objects.create(content_object=self.quartz, tag="clearish") + shiny = TaggedItem.objects.create(content_object=self.quartz, tag="shiny") + clearish = TaggedItem.objects.create(content_object=self.quartz, tag="clearish") ctype = ContentType.objects.get_for_model(self.quartz) q = TaggedItem.objects.filter( content_type__pk=ctype.id, object_id=self.quartz.id ) - self.assertQuerysetEqual(q, [ - "", - "" - ]) + self.assertSequenceEqual(q, [clearish, shiny]) def test_access_via_content_type(self): """ @@ -145,9 +134,10 @@ class GenericRelationsTests(TestCase): ctype = ContentType.objects.get_for_model(self.platypus) - self.assertQuerysetEqual( + self.assertSequenceEqual( Animal.objects.filter(tags__content_type=ctype), - [""]) + [self.platypus], + ) def test_set_foreign_key(self): """ @@ -157,9 +147,7 @@ class GenericRelationsTests(TestCase): tag1.content_object = self.platypus tag1.save() - self.assertQuerysetEqual( - self.platypus.tags.all(), - [""]) + self.assertSequenceEqual(self.platypus.tags.all(), [tag1]) def test_queries_across_generic_relations(self): """ @@ -167,10 +155,10 @@ class GenericRelationsTests(TestCase): there are two TaggedItems with a tag of "fatty", this query only pulls out the one with the content type related to Animals. """ - self.assertQuerysetEqual(Animal.objects.order_by('common_name'), [ - "", - "" - ]) + self.assertSequenceEqual( + Animal.objects.order_by('common_name'), + [self.lion, self.platypus], + ) def test_queries_content_type_restriction(self): """ @@ -181,10 +169,14 @@ class GenericRelationsTests(TestCase): mpk.tags.create(tag="fatty") self.platypus.tags.create(tag="fatty") - self.assertQuerysetEqual( - Animal.objects.filter(tags__tag='fatty'), [""]) - self.assertQuerysetEqual( - Animal.objects.exclude(tags__tag='fatty'), [""]) + self.assertSequenceEqual( + Animal.objects.filter(tags__tag='fatty'), + [self.platypus], + ) + self.assertSequenceEqual( + Animal.objects.exclude(tags__tag='fatty'), + [self.lion], + ) def test_object_deletion_with_generic_relation(self): """ @@ -236,7 +228,7 @@ class GenericRelationsTests(TestCase): content_type__pk=ctype.id, object_id=self.lion.id, tag="hairy") tag.delete() - self.assertQuerysetEqual(self.lion.tags.all(), [""]) + self.assertSequenceEqual(self.lion.tags.all(), [self.yellow]) self.assertQuerysetEqual(TaggedItem.objects.all(), [ ('fatty', Vegetable, self.bacon.pk), ('salty', Vegetable, self.bacon.pk), @@ -282,32 +274,22 @@ class GenericRelationsTests(TestCase): salty = bacon.tags.create(tag="salty") bacon.tags.set([fatty, salty]) - self.assertQuerysetEqual(bacon.tags.all(), [ - "", - "", - ]) + self.assertSequenceEqual(bacon.tags.all(), [fatty, salty]) bacon.tags.set([fatty]) - self.assertQuerysetEqual(bacon.tags.all(), [ - "", - ]) + self.assertSequenceEqual(bacon.tags.all(), [fatty]) bacon.tags.set([]) - self.assertQuerysetEqual(bacon.tags.all(), []) + self.assertSequenceEqual(bacon.tags.all(), []) bacon.tags.set([fatty, salty], bulk=False, clear=True) - self.assertQuerysetEqual(bacon.tags.all(), [ - "", - "", - ]) + self.assertSequenceEqual(bacon.tags.all(), [fatty, salty]) bacon.tags.set([fatty], bulk=False, clear=True) - self.assertQuerysetEqual(bacon.tags.all(), [ - "", - ]) + self.assertSequenceEqual(bacon.tags.all(), [fatty]) bacon.tags.set([], clear=True) - self.assertQuerysetEqual(bacon.tags.all(), []) + self.assertSequenceEqual(bacon.tags.all(), []) def test_assign(self): bacon = Vegetable.objects.create(name="Bacon", is_yucky=False) @@ -315,18 +297,13 @@ class GenericRelationsTests(TestCase): salty = bacon.tags.create(tag="salty") bacon.tags.set([fatty, salty]) - self.assertQuerysetEqual(bacon.tags.all(), [ - "", - "", - ]) + self.assertSequenceEqual(bacon.tags.all(), [fatty, salty]) bacon.tags.set([fatty]) - self.assertQuerysetEqual(bacon.tags.all(), [ - "", - ]) + self.assertSequenceEqual(bacon.tags.all(), [fatty]) bacon.tags.set([]) - self.assertQuerysetEqual(bacon.tags.all(), []) + self.assertSequenceEqual(bacon.tags.all(), []) def test_assign_with_queryset(self): # Querysets used in reverse GFK assignments are pre-evaluated so their @@ -361,42 +338,35 @@ class GenericRelationsTests(TestCase): bear = Animal.objects.create(common_name="bear") # Create directly - Comparison.objects.create( + c1 = Comparison.objects.create( first_obj=cheetah, other_obj=tiger, comparative="faster" ) - Comparison.objects.create( + c2 = Comparison.objects.create( first_obj=tiger, other_obj=cheetah, comparative="cooler" ) # Create using GenericRelation - tiger.comparisons.create(other_obj=bear, comparative="cooler") - tiger.comparisons.create(other_obj=cheetah, comparative="stronger") - self.assertQuerysetEqual(cheetah.comparisons.all(), [ - "" - ]) + c3 = tiger.comparisons.create(other_obj=bear, comparative="cooler") + c4 = tiger.comparisons.create(other_obj=cheetah, comparative="stronger") + self.assertSequenceEqual(cheetah.comparisons.all(), [c1]) # Filtering works - self.assertQuerysetEqual(tiger.comparisons.filter(comparative="cooler"), [ - "", - "", - ], ordered=False) + self.assertCountEqual( + tiger.comparisons.filter(comparative='cooler'), + [c2, c3], + ) # Filtering and deleting works subjective = ["cooler"] tiger.comparisons.filter(comparative__in=subjective).delete() - self.assertQuerysetEqual(Comparison.objects.all(), [ - "", - "" - ], ordered=False) + self.assertCountEqual(Comparison.objects.all(), [c1, c4]) # If we delete cheetah, Comparisons with cheetah as 'first_obj' will be # deleted since Animal has an explicit GenericRelation to Comparison # through first_obj. Comparisons with cheetah as 'other_obj' will not # be deleted. cheetah.delete() - self.assertQuerysetEqual(Comparison.objects.all(), [ - "" - ]) + self.assertSequenceEqual(Comparison.objects.all(), [c4]) def test_gfk_subclasses(self): # GenericForeignKey should work with subclasses (see #8309) diff --git a/tests/generic_views/test_edit.py b/tests/generic_views/test_edit.py index bdabf1d0d2b..ca7c457124c 100644 --- a/tests/generic_views/test_edit.py +++ b/tests/generic_views/test_edit.py @@ -105,7 +105,7 @@ class CreateViewTests(TestCase): res = self.client.post('/edit/authors/create/', {'name': 'Randall Munroe', 'slug': 'randall-munroe'}) self.assertEqual(res.status_code, 302) self.assertRedirects(res, '/list/authors/') - self.assertQuerysetEqual(Author.objects.all(), ['']) + self.assertQuerysetEqual(Author.objects.values_list('name', flat=True), ['Randall Munroe']) def test_create_invalid(self): res = self.client.post('/edit/authors/create/', {'name': 'A' * 101, 'slug': 'randall-munroe'}) @@ -119,20 +119,20 @@ class CreateViewTests(TestCase): self.assertEqual(res.status_code, 302) artist = Artist.objects.get(name='Rene Magritte') self.assertRedirects(res, '/detail/artist/%d/' % artist.pk) - self.assertQuerysetEqual(Artist.objects.all(), ['']) + self.assertQuerysetEqual(Artist.objects.all(), [artist]) def test_create_with_redirect(self): res = self.client.post('/edit/authors/create/redirect/', {'name': 'Randall Munroe', 'slug': 'randall-munroe'}) self.assertEqual(res.status_code, 302) self.assertRedirects(res, '/edit/authors/create/') - self.assertQuerysetEqual(Author.objects.all(), ['']) + self.assertQuerysetEqual(Author.objects.values_list('name', flat=True), ['Randall Munroe']) def test_create_with_interpolated_redirect(self): res = self.client.post( '/edit/authors/create/interpolate_redirect/', {'name': 'Randall Munroe', 'slug': 'randall-munroe'} ) - self.assertQuerysetEqual(Author.objects.all(), ['']) + self.assertQuerysetEqual(Author.objects.values_list('name', flat=True), ['Randall Munroe']) self.assertEqual(res.status_code, 302) pk = Author.objects.first().pk self.assertRedirects(res, '/edit/author/%d/update/' % pk) @@ -157,7 +157,7 @@ class CreateViewTests(TestCase): self.assertEqual(res.status_code, 302) obj = Author.objects.get(slug='randall-munroe') self.assertRedirects(res, reverse('author_detail', kwargs={'pk': obj.pk})) - self.assertQuerysetEqual(Author.objects.all(), ['']) + self.assertQuerysetEqual(Author.objects.all(), [obj]) def test_create_without_redirect(self): msg = ( @@ -239,7 +239,7 @@ class UpdateViewTests(TestCase): ) self.assertEqual(res.status_code, 302) self.assertRedirects(res, '/list/authors/') - self.assertQuerysetEqual(Author.objects.all(), ['']) + self.assertQuerysetEqual(Author.objects.values_list('name', flat=True), ['Randall Munroe (xkcd)']) def test_update_invalid(self): res = self.client.post( @@ -249,7 +249,7 @@ class UpdateViewTests(TestCase): self.assertEqual(res.status_code, 200) self.assertTemplateUsed(res, 'generic_views/author_form.html') self.assertEqual(len(res.context['form'].errors), 1) - self.assertQuerysetEqual(Author.objects.all(), ['']) + self.assertQuerysetEqual(Author.objects.all(), [self.author]) self.assertEqual(res.context['view'].get_form_called_count, 1) def test_update_with_object_url(self): @@ -257,7 +257,7 @@ class UpdateViewTests(TestCase): res = self.client.post('/edit/artists/%d/update/' % a.pk, {'name': 'Rene Magritte'}) self.assertEqual(res.status_code, 302) self.assertRedirects(res, '/detail/artist/%d/' % a.pk) - self.assertQuerysetEqual(Artist.objects.all(), ['']) + self.assertQuerysetEqual(Artist.objects.all(), [a]) def test_update_with_redirect(self): res = self.client.post( @@ -266,14 +266,14 @@ class UpdateViewTests(TestCase): ) self.assertEqual(res.status_code, 302) self.assertRedirects(res, '/edit/authors/create/') - self.assertQuerysetEqual(Author.objects.all(), ['']) + self.assertQuerysetEqual(Author.objects.values_list('name', flat=True), ['Randall Munroe (author of xkcd)']) def test_update_with_interpolated_redirect(self): res = self.client.post( '/edit/author/%d/update/interpolate_redirect/' % self.author.pk, {'name': 'Randall Munroe (author of xkcd)', 'slug': 'randall-munroe'} ) - self.assertQuerysetEqual(Author.objects.all(), ['']) + self.assertQuerysetEqual(Author.objects.values_list('name', flat=True), ['Randall Munroe (author of xkcd)']) self.assertEqual(res.status_code, 302) pk = Author.objects.first().pk self.assertRedirects(res, '/edit/author/%d/update/' % pk) @@ -301,7 +301,7 @@ class UpdateViewTests(TestCase): ) self.assertEqual(res.status_code, 302) self.assertRedirects(res, '/detail/author/%d/' % self.author.pk) - self.assertQuerysetEqual(Author.objects.all(), ['']) + self.assertQuerysetEqual(Author.objects.values_list('name', flat=True), ['Randall Munroe (author of xkcd)']) def test_update_without_redirect(self): msg = ( @@ -327,7 +327,7 @@ class UpdateViewTests(TestCase): res = self.client.post('/edit/author/update/', {'name': 'Randall Munroe (xkcd)', 'slug': 'randall-munroe'}) self.assertEqual(res.status_code, 302) self.assertRedirects(res, '/list/authors/') - self.assertQuerysetEqual(Author.objects.all(), ['']) + self.assertQuerysetEqual(Author.objects.values_list('name', flat=True), ['Randall Munroe (xkcd)']) @override_settings(ROOT_URLCONF='generic_views.urls') diff --git a/tests/lookup/test_timefield.py b/tests/lookup/test_timefield.py index 6ef1d794e22..1fa02bc5964 100644 --- a/tests/lookup/test_timefield.py +++ b/tests/lookup/test_timefield.py @@ -13,22 +13,19 @@ class TimeFieldLookupTests(TestCase): self.al3 = Alarm.objects.create(desc='Precise', time='12:34:56') def test_hour_lookups(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Alarm.objects.filter(time__hour=5), - [''], - ordered=False + [self.al1], ) def test_minute_lookups(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Alarm.objects.filter(time__minute=30), - [''], - ordered=False + [self.al1], ) def test_second_lookups(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Alarm.objects.filter(time__second=56), - [''], - ordered=False + [self.al3], ) diff --git a/tests/lookup/tests.py b/tests/lookup/tests.py index 9094542808e..9962d349373 100644 --- a/tests/lookup/tests.py +++ b/tests/lookup/tests.py @@ -84,23 +84,17 @@ class LookupTests(TestCase): def test_lookup_int_as_str(self): # Integer value can be queried using string - self.assertQuerysetEqual(Article.objects.filter(id__iexact=str(self.a1.id)), - ['']) + self.assertSequenceEqual( + Article.objects.filter(id__iexact=str(self.a1.id)), + [self.a1], + ) @skipUnlessDBFeature('supports_date_lookup_using_string') def test_lookup_date_as_str(self): # A date lookup can be performed using a string search - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(pub_date__startswith='2005'), - [ - '', - '', - '', - '', - '', - '', - '', - ] + [self.a5, self.a6, self.a4, self.a2, self.a3, self.a7, self.a1], ) def test_iterator(self): @@ -492,96 +486,48 @@ class LookupTests(TestCase): def test_escaping(self): # Underscores, percent signs and backslashes have special meaning in the # underlying SQL code, but Django handles the quoting of them automatically. - Article.objects.create(headline='Article_ with underscore', pub_date=datetime(2005, 11, 20)) + a8 = Article.objects.create(headline='Article_ with underscore', pub_date=datetime(2005, 11, 20)) - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(headline__startswith='Article'), - [ - '', - '', - '', - '', - '', - '', - '', - '', - ] + [a8, self.a5, self.a6, self.a4, self.a2, self.a3, self.a7, self.a1], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(headline__startswith='Article_'), - [''] + [a8], ) - Article.objects.create(headline='Article% with percent sign', pub_date=datetime(2005, 11, 21)) - self.assertQuerysetEqual( + a9 = Article.objects.create(headline='Article% with percent sign', pub_date=datetime(2005, 11, 21)) + self.assertSequenceEqual( Article.objects.filter(headline__startswith='Article'), - [ - '', - '', - '', - '', - '', - '', - '', - '', - '', - ] + [a9, a8, self.a5, self.a6, self.a4, self.a2, self.a3, self.a7, self.a1], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(headline__startswith='Article%'), - [''] + [a9], ) - Article.objects.create(headline='Article with \\ backslash', pub_date=datetime(2005, 11, 22)) - self.assertQuerysetEqual( + a10 = Article.objects.create(headline='Article with \\ backslash', pub_date=datetime(2005, 11, 22)) + self.assertSequenceEqual( Article.objects.filter(headline__contains='\\'), - [r''] + [a10], ) def test_exclude(self): - Article.objects.bulk_create([ - Article(headline='Article_ with underscore', pub_date=datetime(2005, 11, 20)), - Article(headline='Article% with percent sign', pub_date=datetime(2005, 11, 21)), - Article(headline='Article with \\ backslash', pub_date=datetime(2005, 11, 22)), - ]) + pub_date = datetime(2005, 11, 20) + a8 = Article.objects.create(headline='Article_ with underscore', pub_date=pub_date) + a9 = Article.objects.create(headline='Article% with percent sign', pub_date=pub_date) + a10 = Article.objects.create(headline='Article with \\ backslash', pub_date=pub_date) # exclude() is the opposite of filter() when doing lookups: - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(headline__contains='Article').exclude(headline__contains='with'), - [ - '', - '', - '', - '', - '', - '', - '', - ] + [self.a5, self.a6, self.a4, self.a2, self.a3, self.a7, self.a1], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.exclude(headline__startswith="Article_"), - [ - '', - '', - '', - '', - '', - '', - '', - '', - '', - ] + [a10, a9, self.a5, self.a6, self.a4, self.a2, self.a3, self.a7, self.a1], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.exclude(headline="Article 7"), - [ - '', - '', - '', - '', - '', - '', - '', - '', - '', - ] + [a10, a9, a8, self.a5, self.a6, self.a4, self.a2, self.a3, self.a1], ) def test_none(self): @@ -594,17 +540,9 @@ class LookupTests(TestCase): self.assertQuerysetEqual(Article.objects.none().iterator(), []) def test_in(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.exclude(id__in=[]), - [ - '', - '', - '', - '', - '', - '', - '', - ] + [self.a5, self.a6, self.a4, self.a2, self.a3, self.a7, self.a1], ) def test_in_empty_list(self): @@ -706,49 +644,52 @@ class LookupTests(TestCase): # zero-or-more self.assertQuerysetEqual( Article.objects.filter(headline__regex=r'fo*'), - ['', '', '', ''] + Article.objects.filter(headline__in=['f', 'fo', 'foo', 'fooo']), ) self.assertQuerysetEqual( Article.objects.filter(headline__iregex=r'fo*'), - [ - '', - '', - '', - '', - '', - ] + Article.objects.filter(headline__in=['f', 'fo', 'foo', 'fooo', 'hey-Foo']), ) # one-or-more self.assertQuerysetEqual( Article.objects.filter(headline__regex=r'fo+'), - ['', '', ''] + Article.objects.filter(headline__in=['fo', 'foo', 'fooo']), ) # wildcard self.assertQuerysetEqual( Article.objects.filter(headline__regex=r'fooo?'), - ['', ''] + Article.objects.filter(headline__in=['foo', 'fooo']), ) # leading anchor self.assertQuerysetEqual( Article.objects.filter(headline__regex=r'^b'), - ['', '', ''] + Article.objects.filter(headline__in=['bar', 'baxZ', 'baz']), + ) + self.assertQuerysetEqual( + Article.objects.filter(headline__iregex=r'^a'), + Article.objects.filter(headline='AbBa'), ) - self.assertQuerysetEqual(Article.objects.filter(headline__iregex=r'^a'), ['']) # trailing anchor - self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'z$'), ['']) + self.assertQuerysetEqual( + Article.objects.filter(headline__regex=r'z$'), + Article.objects.filter(headline='baz'), + ) self.assertQuerysetEqual( Article.objects.filter(headline__iregex=r'z$'), - ['', ''] + Article.objects.filter(headline__in=['baxZ', 'baz']), ) # character sets self.assertQuerysetEqual( Article.objects.filter(headline__regex=r'ba[rz]'), - ['', ''] + Article.objects.filter(headline__in=['bar', 'baz']), + ) + self.assertQuerysetEqual( + Article.objects.filter(headline__regex=r'ba.[RxZ]'), + Article.objects.filter(headline='baxZ'), ) - self.assertQuerysetEqual(Article.objects.filter(headline__regex=r'ba.[RxZ]'), ['']) self.assertQuerysetEqual( Article.objects.filter(headline__iregex=r'ba[RxZ]'), - ['', '', ''] + Article.objects.filter(headline__in=['bar', 'baxZ', 'baz']), ) # and more articles: @@ -765,48 +706,48 @@ class LookupTests(TestCase): # alternation self.assertQuerysetEqual( Article.objects.filter(headline__regex=r'oo(f|b)'), - [ - '', - '', - '', - '', - ] + Article.objects.filter(headline__in=[ + 'barfoobaz', + 'foobar', + 'foobarbaz', + 'foobaz', + ]), ) self.assertQuerysetEqual( Article.objects.filter(headline__iregex=r'oo(f|b)'), - [ - '', - '', - '', - '', - '', - ] + Article.objects.filter(headline__in=[ + 'barfoobaz', + 'foobar', + 'foobarbaz', + 'foobaz', + 'ooF', + ]), ) self.assertQuerysetEqual( Article.objects.filter(headline__regex=r'^foo(f|b)'), - ['', '', ''] + Article.objects.filter(headline__in=['foobar', 'foobarbaz', 'foobaz']), ) # greedy matching self.assertQuerysetEqual( Article.objects.filter(headline__regex=r'b.*az'), - [ - '', - '', - '', - '', - '', - ] + Article.objects.filter(headline__in=[ + 'barfoobaz', + 'baz', + 'bazbaRFOO', + 'foobarbaz', + 'foobaz', + ]), ) self.assertQuerysetEqual( Article.objects.filter(headline__iregex=r'b.*ar'), - [ - '', - '', - '', - '', - '', - ] + Article.objects.filter(headline__in=[ + 'bar', + 'barfoobaz', + 'bazbaRFOO', + 'foobar', + 'foobarbaz', + ]), ) @skipUnlessDBFeature('supports_regex_backreferencing') @@ -823,8 +764,8 @@ class LookupTests(TestCase): Article(pub_date=now, headline='bazbaRFOO'), ]) self.assertQuerysetEqual( - Article.objects.filter(headline__regex=r'b(.).*b\1'), - ['', '', ''] + Article.objects.filter(headline__regex=r'b(.).*b\1').values_list('headline', flat=True), + ['barfoobaz', 'bazbaRFOO', 'foobarbaz'], ) def test_regex_null(self): @@ -838,8 +779,8 @@ class LookupTests(TestCase): """ A regex lookup does not fail on non-string fields """ - Season.objects.create(year=2013, gt=444) - self.assertQuerysetEqual(Season.objects.filter(gt__regex=r'^444$'), ['']) + s = Season.objects.create(year=2013, gt=444) + self.assertQuerysetEqual(Season.objects.filter(gt__regex=r'^444$'), [s]) def test_regex_non_ascii(self): """ @@ -928,31 +869,21 @@ class LookupTests(TestCase): self.assertEqual(Player.objects.filter(games__season__gt__gt=222).distinct().count(), 2) def test_chain_date_time_lookups(self): - self.assertQuerysetEqual( + self.assertCountEqual( Article.objects.filter(pub_date__month__gt=7), - ['', ''], - ordered=False + [self.a5, self.a6], ) - self.assertQuerysetEqual( + self.assertCountEqual( Article.objects.filter(pub_date__day__gte=27), - ['', '', - '', ''], - ordered=False + [self.a2, self.a3, self.a4, self.a7], ) - self.assertQuerysetEqual( + self.assertCountEqual( Article.objects.filter(pub_date__hour__lt=8), - ['', '', - '', '', - ''], - ordered=False + [self.a1, self.a2, self.a3, self.a4, self.a7], ) - self.assertQuerysetEqual( + self.assertCountEqual( Article.objects.filter(pub_date__minute__lte=0), - ['', '', - '', '', - '', '', - ''], - ordered=False + [self.a1, self.a2, self.a3, self.a4, self.a5, self.a6, self.a7], ) def test_exact_none_transform(self): diff --git a/tests/m2m_regress/tests.py b/tests/m2m_regress/tests.py index c27fd8a6b24..a2c7fc99cc0 100644 --- a/tests/m2m_regress/tests.py +++ b/tests/m2m_regress/tests.py @@ -25,11 +25,11 @@ class M2MRegressionTests(TestCase): e1.topics.add(t1) e1.related.add(t2) - self.assertQuerysetEqual(s1.references.all(), [""]) - self.assertQuerysetEqual(s1.related.all(), [""]) + self.assertSequenceEqual(s1.references.all(), [s2]) + self.assertSequenceEqual(s1.related.all(), [s3]) - self.assertQuerysetEqual(e1.topics.all(), [""]) - self.assertQuerysetEqual(e1.related.all(), [""]) + self.assertSequenceEqual(e1.topics.all(), [t1]) + self.assertSequenceEqual(e1.related.all(), [t2]) def test_internal_related_name_not_in_error_msg(self): # The secret internal related names for self-referential many-to-many @@ -51,8 +51,8 @@ class M2MRegressionTests(TestCase): sr_sibling.save() sr_child.related.add(sr_sibling) - self.assertQuerysetEqual(sr_child.related.all(), [""]) - self.assertQuerysetEqual(sr_sibling.related.all(), [""]) + self.assertSequenceEqual(sr_child.related.all(), [sr_sibling.selfrefer_ptr]) + self.assertSequenceEqual(sr_sibling.related.all(), [sr_child.selfrefer_ptr]) def test_m2m_pk_field_type(self): # Regression for #11311 - The primary key for models in a m2m relation @@ -73,8 +73,8 @@ class M2MRegressionTests(TestCase): c1.tags.set([t1, t2]) c1 = TagCollection.objects.get(name='c1') - self.assertQuerysetEqual(c1.tags.all(), ["", ""], ordered=False) - self.assertQuerysetEqual(t1.tag_collections.all(), [""]) + self.assertCountEqual(c1.tags.all(), [t1, t2]) + self.assertCountEqual(t1.tag_collections.all(), [c1]) def test_manager_class_caching(self): e1 = Entry.objects.create() @@ -106,7 +106,7 @@ class M2MRegressionTests(TestCase): c1.tags.set(7) c1.refresh_from_db() - self.assertQuerysetEqual(c1.tags.order_by('name'), ["", ""]) + self.assertSequenceEqual(c1.tags.order_by('name'), [t1, t2]) def test_multiple_forwards_only_m2m(self): # Regression for #24505 - Multiple ManyToManyFields to same "to" @@ -116,5 +116,5 @@ class M2MRegressionTests(TestCase): post = Post.objects.create() post.primary_lines.add(foo) post.secondary_lines.add(bar) - self.assertQuerysetEqual(post.primary_lines.all(), ['']) - self.assertQuerysetEqual(post.secondary_lines.all(), ['']) + self.assertSequenceEqual(post.primary_lines.all(), [foo]) + self.assertSequenceEqual(post.secondary_lines.all(), [bar]) diff --git a/tests/m2m_through/tests.py b/tests/m2m_through/tests.py index ec3c481dd23..6262596dd06 100644 --- a/tests/m2m_through/tests.py +++ b/tests/m2m_through/tests.py @@ -42,20 +42,12 @@ class M2mThroughTests(TestCase): ) def test_filter_on_intermediate_model(self): - Membership.objects.create(person=self.jim, group=self.rock) - Membership.objects.create(person=self.jane, group=self.rock) + m1 = Membership.objects.create(person=self.jim, group=self.rock) + m2 = Membership.objects.create(person=self.jane, group=self.rock) queryset = Membership.objects.filter(group=self.rock) - expected = [ - '', - '', - ] - - self.assertQuerysetEqual( - queryset, - expected - ) + self.assertSequenceEqual(queryset, [m1, m2]) def test_add_on_m2m_with_intermediate_model(self): self.rock.members.add(self.bob, through_defaults={'invite_reason': 'He is good.'}) @@ -372,12 +364,8 @@ class M2mThroughTests(TestCase): ) def test_custom_related_name_doesnt_conflict_with_fky_related_name(self): - CustomMembership.objects.create(person=self.bob, group=self.rock) - - self.assertQuerysetEqual( - self.bob.custom_person_related_name.all(), - [''] - ) + c = CustomMembership.objects.create(person=self.bob, group=self.rock) + self.assertSequenceEqual(self.bob.custom_person_related_name.all(), [c]) def test_through_fields(self): """ diff --git a/tests/m2m_through_regress/tests.py b/tests/m2m_through_regress/tests.py index b0e12e27452..93d2260054e 100644 --- a/tests/m2m_through_regress/tests.py +++ b/tests/m2m_through_regress/tests.py @@ -32,53 +32,31 @@ class M2MThroughTestCase(TestCase): cls.jane_rock = UserMembership.objects.create(user=cls.jane, group=cls.rock) def test_retrieve_reverse_m2m_items(self): - self.assertQuerysetEqual( - self.bob.group_set.all(), [ - "", - "", - ], - ordered=False - ) + self.assertCountEqual(self.bob.group_set.all(), [self.rock, self.roll]) def test_retrieve_forward_m2m_items(self): - self.assertQuerysetEqual( - self.roll.members.all(), [ - "", - ] - ) + self.assertSequenceEqual(self.roll.members.all(), [self.bob]) def test_retrieve_reverse_m2m_items_via_custom_id_intermediary(self): - self.assertQuerysetEqual( - self.frank.group_set.all(), [ - "", - "", - ], - ordered=False - ) + self.assertCountEqual(self.frank.group_set.all(), [self.rock, self.roll]) def test_retrieve_forward_m2m_items_via_custom_id_intermediary(self): - self.assertQuerysetEqual( - self.roll.user_members.all(), [ - "", - ] - ) + self.assertSequenceEqual(self.roll.user_members.all(), [self.frank]) def test_join_trimming_forwards(self): """ Too many copies of the intermediate table aren't involved when doing a join (#8046, #8254). """ - self.assertQuerysetEqual( - self.rock.members.filter(membership__price=50), [ - "", - ] + self.assertSequenceEqual( + self.rock.members.filter(membership__price=50), + [self.jim], ) def test_join_trimming_reverse(self): - self.assertQuerysetEqual( - self.bob.group_set.filter(membership__price=50), [ - "", - ] + self.assertSequenceEqual( + self.bob.group_set.filter(membership__price=50), + [self.roll], ) @@ -139,26 +117,18 @@ class ToFieldThroughTests(TestCase): cls.unused_car2 = Car.objects.create(make="Wartburg") def test_to_field(self): - self.assertQuerysetEqual( - self.car.drivers.all(), - [""] - ) + self.assertSequenceEqual(self.car.drivers.all(), [self.driver]) def test_to_field_reverse(self): - self.assertQuerysetEqual( - self.driver.car_set.all(), - [""] - ) + self.assertSequenceEqual(self.driver.car_set.all(), [self.car]) def test_to_field_clear_reverse(self): self.driver.car_set.clear() - self.assertQuerysetEqual( - self.driver.car_set.all(), []) + self.assertSequenceEqual(self.driver.car_set.all(), []) def test_to_field_clear(self): self.car.drivers.clear() - self.assertQuerysetEqual( - self.car.drivers.all(), []) + self.assertSequenceEqual(self.car.drivers.all(), []) # Low level tests for _add_items and _remove_items. We test these methods # because .add/.remove aren't available for m2m fields with through, but @@ -166,15 +136,12 @@ class ToFieldThroughTests(TestCase): # sure these methods are ready if the ability to use .add or .remove with # to_field relations is added some day. def test_add(self): - self.assertQuerysetEqual( - self.car.drivers.all(), - [""] - ) + self.assertSequenceEqual(self.car.drivers.all(), [self.driver]) # Yikes - barney is going to drive... self.car.drivers._add_items('car', 'driver', self.unused_driver) - self.assertQuerysetEqual( + self.assertSequenceEqual( self.car.drivers.all(), - ["", ""] + [self.unused_driver, self.driver], ) def test_m2m_relations_unusable_on_null_to_field(self): @@ -202,16 +169,9 @@ class ToFieldThroughTests(TestCase): def test_add_reverse(self): car2 = Car.objects.create(make="Honda") - self.assertQuerysetEqual( - self.driver.car_set.all(), - [""] - ) + self.assertCountEqual(self.driver.car_set.all(), [self.car]) self.driver.car_set._add_items('driver', 'car', car2) - self.assertQuerysetEqual( - self.driver.car_set.all(), - ["", ""], - ordered=False - ) + self.assertCountEqual(self.driver.car_set.all(), [self.car, car2]) def test_add_null_reverse(self): nullcar = Car.objects.create(make=None) @@ -229,22 +189,14 @@ class ToFieldThroughTests(TestCase): nulldriver.car_set._add_items('driver', 'car', self.car) def test_remove(self): - self.assertQuerysetEqual( - self.car.drivers.all(), - [""] - ) + self.assertSequenceEqual(self.car.drivers.all(), [self.driver]) self.car.drivers._remove_items('car', 'driver', self.driver) - self.assertQuerysetEqual( - self.car.drivers.all(), []) + self.assertSequenceEqual(self.car.drivers.all(), []) def test_remove_reverse(self): - self.assertQuerysetEqual( - self.driver.car_set.all(), - [""] - ) + self.assertSequenceEqual(self.driver.car_set.all(), [self.car]) self.driver.car_set._remove_items('driver', 'car', self.car) - self.assertQuerysetEqual( - self.driver.car_set.all(), []) + self.assertSequenceEqual(self.driver.car_set.all(), []) class ThroughLoadDataTestCase(TestCase): diff --git a/tests/m2o_recursive/tests.py b/tests/m2o_recursive/tests.py index 95b60a8e499..1b9a72a796c 100644 --- a/tests/m2o_recursive/tests.py +++ b/tests/m2o_recursive/tests.py @@ -11,11 +11,10 @@ class ManyToOneRecursiveTests(TestCase): cls.c = Category.objects.create(id=None, name='Child category', parent=cls.r) def test_m2o_recursive(self): - self.assertQuerysetEqual(self.r.child_set.all(), - ['']) + self.assertSequenceEqual(self.r.child_set.all(), [self.c]) self.assertEqual(self.r.child_set.get(name__startswith='Child').id, self.c.id) self.assertIsNone(self.r.parent) - self.assertQuerysetEqual(self.c.child_set.all(), []) + self.assertSequenceEqual(self.c.child_set.all(), []) self.assertEqual(self.c.parent.id, self.r.id) @@ -30,9 +29,7 @@ class MultipleManyToOneRecursiveTests(TestCase): def test_m2o_recursive2(self): self.assertEqual(self.kid.mother.id, self.mom.id) self.assertEqual(self.kid.father.id, self.dad.id) - self.assertQuerysetEqual(self.dad.fathers_child_set.all(), - ['']) - self.assertQuerysetEqual(self.mom.mothers_child_set.all(), - ['']) - self.assertQuerysetEqual(self.kid.mothers_child_set.all(), []) - self.assertQuerysetEqual(self.kid.fathers_child_set.all(), []) + self.assertSequenceEqual(self.dad.fathers_child_set.all(), [self.kid]) + self.assertSequenceEqual(self.mom.mothers_child_set.all(), [self.kid]) + self.assertSequenceEqual(self.kid.mothers_child_set.all(), []) + self.assertSequenceEqual(self.kid.fathers_child_set.all(), []) diff --git a/tests/managers_regress/tests.py b/tests/managers_regress/tests.py index 7fa6815959c..421e30ca458 100644 --- a/tests/managers_regress/tests.py +++ b/tests/managers_regress/tests.py @@ -14,46 +14,44 @@ from .models import ( class ManagersRegressionTests(TestCase): def test_managers(self): - Child1.objects.create(name='fred', data='a1') - Child1.objects.create(name='barney', data='a2') - Child2.objects.create(name='fred', data='b1', value=1) - Child2.objects.create(name='barney', data='b2', value=42) - Child3.objects.create(name='fred', data='c1', comment='yes') - Child3.objects.create(name='barney', data='c2', comment='no') - Child4.objects.create(name='fred', data='d1') - Child4.objects.create(name='barney', data='d2') - Child5.objects.create(name='fred', comment='yes') + a1 = Child1.objects.create(name='fred', data='a1') + a2 = Child1.objects.create(name='barney', data='a2') + b1 = Child2.objects.create(name='fred', data='b1', value=1) + b2 = Child2.objects.create(name='barney', data='b2', value=42) + c1 = Child3.objects.create(name='fred', data='c1', comment='yes') + c2 = Child3.objects.create(name='barney', data='c2', comment='no') + d1 = Child4.objects.create(name='fred', data='d1') + d2 = Child4.objects.create(name='barney', data='d2') + fred1 = Child5.objects.create(name='fred', comment='yes') Child5.objects.create(name='barney', comment='no') - Child6.objects.create(name='fred', data='f1', value=42) - Child6.objects.create(name='barney', data='f2', value=42) - Child7.objects.create(name='fred') - Child7.objects.create(name='barney') + f1 = Child6.objects.create(name='fred', data='f1', value=42) + f2 = Child6.objects.create(name='barney', data='f2', value=42) + fred2 = Child7.objects.create(name='fred') + barney = Child7.objects.create(name='barney') - self.assertQuerysetEqual(Child1.manager1.all(), [""]) - self.assertQuerysetEqual(Child1.manager2.all(), [""]) - self.assertQuerysetEqual(Child1._default_manager.all(), [""]) + self.assertSequenceEqual(Child1.manager1.all(), [a1]) + self.assertSequenceEqual(Child1.manager2.all(), [a2]) + self.assertSequenceEqual(Child1._default_manager.all(), [a1]) - self.assertQuerysetEqual(Child2._default_manager.all(), [""]) - self.assertQuerysetEqual(Child2.restricted.all(), [""]) + self.assertSequenceEqual(Child2._default_manager.all(), [b1]) + self.assertSequenceEqual(Child2.restricted.all(), [b2]) - self.assertQuerysetEqual(Child3._default_manager.all(), [""]) - self.assertQuerysetEqual(Child3.manager1.all(), [""]) - self.assertQuerysetEqual(Child3.manager2.all(), [""]) + self.assertSequenceEqual(Child3._default_manager.all(), [c1]) + self.assertSequenceEqual(Child3.manager1.all(), [c1]) + self.assertSequenceEqual(Child3.manager2.all(), [c2]) # Since Child6 inherits from Child4, the corresponding rows from f1 and # f2 also appear here. This is the expected result. - self.assertQuerysetEqual(Child4._default_manager.order_by('data'), [ - "", - "", - "", - "", - ]) - self.assertQuerysetEqual(Child4.manager1.all(), ["", ""], ordered=False) - self.assertQuerysetEqual(Child5._default_manager.all(), [""]) - self.assertQuerysetEqual(Child6._default_manager.all(), ["", ""], ordered=False) - self.assertQuerysetEqual( + self.assertSequenceEqual( + Child4._default_manager.order_by('data'), + [d1, d2, f1.child4_ptr, f2.child4_ptr], + ) + self.assertCountEqual(Child4.manager1.all(), [d1, f1.child4_ptr]) + self.assertCountEqual(Child5._default_manager.all(), [fred1]) + self.assertCountEqual(Child6._default_manager.all(), [f1, f2]) + self.assertSequenceEqual( Child7._default_manager.order_by('name'), - ["", ""] + [barney, fred2], ) def test_abstract_manager(self): diff --git a/tests/many_to_many/tests.py b/tests/many_to_many/tests.py index 1359cf07730..9242be9a9f0 100644 --- a/tests/many_to_many/tests.py +++ b/tests/many_to_many/tests.py @@ -44,7 +44,7 @@ class ManyToManyTests(TestCase): a5.save() # Associate the Article with a Publication. a5.publications.add(self.p1) - self.assertQuerysetEqual(a5.publications.all(), ['']) + self.assertSequenceEqual(a5.publications.all(), [self.p1]) # Create another Article, and set it to appear in both Publications. a6 = Article(headline='ESA uses Python') a6.save() @@ -52,13 +52,9 @@ class ManyToManyTests(TestCase): a6.publications.add(self.p3) # Adding a second time is OK a6.publications.add(self.p3) - self.assertQuerysetEqual( + self.assertSequenceEqual( a6.publications.all(), - [ - '', - '', - '', - ] + [self.p2, self.p3, self.p1], ) # Adding an object of the wrong type raises TypeError @@ -68,42 +64,31 @@ class ManyToManyTests(TestCase): a6.publications.add(a5) # Add a Publication directly via publications.add by using keyword arguments. - a6.publications.create(title='Highlights for Adults') - self.assertQuerysetEqual( + p5 = a6.publications.create(title='Highlights for Adults') + self.assertSequenceEqual( a6.publications.all(), - [ - '', - '', - '', - '', - ] + [p5, self.p2, self.p3, self.p1], ) def test_add_remove_set_by_pk(self): a5 = Article.objects.create(headline='Django lets you create Web apps easily') a5.publications.add(self.p1.pk) - self.assertQuerysetEqual( - a5.publications.all(), - [''], - ) + self.assertSequenceEqual(a5.publications.all(), [self.p1]) a5.publications.set([self.p2.pk]) - self.assertQuerysetEqual( - a5.publications.all(), - [''], - ) + self.assertSequenceEqual(a5.publications.all(), [self.p2]) a5.publications.remove(self.p2.pk) - self.assertQuerysetEqual(a5.publications.all(), []) + self.assertSequenceEqual(a5.publications.all(), []) def test_add_remove_set_by_to_field(self): user_1 = User.objects.create(username='Jean') user_2 = User.objects.create(username='Joe') a5 = Article.objects.create(headline='Django lets you create Web apps easily') a5.authors.add(user_1.username) - self.assertQuerysetEqual(a5.authors.all(), ['']) + self.assertSequenceEqual(a5.authors.all(), [user_1]) a5.authors.set([user_2.username]) - self.assertQuerysetEqual(a5.authors.all(), ['']) + self.assertSequenceEqual(a5.authors.all(), [user_2]) a5.authors.remove(user_2.username) - self.assertQuerysetEqual(a5.authors.all(), []) + self.assertSequenceEqual(a5.authors.all(), []) def test_add_remove_invalid_type(self): msg = "Field 'id' expected a number but got 'invalid'." @@ -116,37 +101,22 @@ class ManyToManyTests(TestCase): a5 = Article(headline='NASA finds intelligent life on Mars') a5.save() self.p2.article_set.add(a5) - self.assertQuerysetEqual( + self.assertSequenceEqual( self.p2.article_set.all(), - [ - '', - '', - '', - '', - ] + [self.a3, a5, self.a2, self.a4], ) - self.assertQuerysetEqual(a5.publications.all(), ['']) + self.assertSequenceEqual(a5.publications.all(), [self.p2]) # Adding via the other end using keywords - self.p2.article_set.create(headline='Carbon-free diet works wonders') - self.assertQuerysetEqual( + a6 = self.p2.article_set.create(headline='Carbon-free diet works wonders') + self.assertSequenceEqual( self.p2.article_set.all(), - [ - '', - '', - '', - '', - '', - ]) + [a6, self.a3, a5, self.a2, self.a4], + ) a6 = self.p2.article_set.all()[3] - self.assertQuerysetEqual( + self.assertSequenceEqual( a6.publications.all(), - [ - '', - '', - '', - '', - ] + [self.p4, self.p2, self.p3, self.p1], ) @skipUnlessDBFeature('supports_ignore_conflicts') @@ -182,293 +152,195 @@ class ManyToManyTests(TestCase): def test_related_sets(self): # Article objects have access to their related Publication objects. - self.assertQuerysetEqual(self.a1.publications.all(), ['']) - self.assertQuerysetEqual( + self.assertSequenceEqual(self.a1.publications.all(), [self.p1]) + self.assertSequenceEqual( self.a2.publications.all(), - [ - '', - '', - '', - '', - ] + [self.p4, self.p2, self.p3, self.p1], ) # Publication objects have access to their related Article objects. - self.assertQuerysetEqual( + self.assertSequenceEqual( self.p2.article_set.all(), - [ - '', - '', - '', - ] + [self.a3, self.a2, self.a4], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( self.p1.article_set.all(), - [ - '', - '', - ] + [self.a1, self.a2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Publication.objects.get(id=self.p4.id).article_set.all(), - [''] + [self.a2], ) def test_selects(self): # We can perform kwarg queries across m2m relationships - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(publications__id__exact=self.p1.id), - [ - '', - '', - ]) - self.assertQuerysetEqual( + [self.a1, self.a2], + ) + self.assertSequenceEqual( Article.objects.filter(publications__pk=self.p1.id), - [ - '', - '', - ] + [self.a1, self.a2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(publications=self.p1.id), - [ - '', - '', - ] + [self.a1, self.a2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(publications=self.p1), - [ - '', - '', - ] + [self.a1, self.a2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(publications__title__startswith="Science"), - [ - '', - '', - '', - '', - ] + [self.a3, self.a2, self.a2, self.a4] ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(publications__title__startswith="Science").distinct(), - [ - '', - '', - '', - ] + [self.a3, self.a2, self.a4], ) # The count() function respects distinct() as well. self.assertEqual(Article.objects.filter(publications__title__startswith="Science").count(), 4) self.assertEqual(Article.objects.filter(publications__title__startswith="Science").distinct().count(), 3) - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(publications__in=[self.p1.id, self.p2.id]).distinct(), - [ - '', - '', - '', - '', - ]) - self.assertQuerysetEqual( - Article.objects.filter(publications__in=[self.p1.id, self.p2]).distinct(), - [ - '', - '', - '', - '', - ] + [self.a1, self.a3, self.a2, self.a4], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( + Article.objects.filter(publications__in=[self.p1.id, self.p2]).distinct(), + [self.a1, self.a3, self.a2, self.a4], + ) + self.assertSequenceEqual( Article.objects.filter(publications__in=[self.p1, self.p2]).distinct(), - [ - '', - '', - '', - '', - ] + [self.a1, self.a3, self.a2, self.a4], ) # Excluding a related item works as you would expect, too (although the SQL # involved is a little complex). - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.exclude(publications=self.p2), - [''] + [self.a1], ) def test_reverse_selects(self): # Reverse m2m queries are supported (i.e., starting at the table that # doesn't have a ManyToManyField). - python_journal = [''] - self.assertQuerysetEqual(Publication.objects.filter(id__exact=self.p1.id), python_journal) - self.assertQuerysetEqual(Publication.objects.filter(pk=self.p1.id), python_journal) - self.assertQuerysetEqual( + python_journal = [self.p1] + self.assertSequenceEqual(Publication.objects.filter(id__exact=self.p1.id), python_journal) + self.assertSequenceEqual(Publication.objects.filter(pk=self.p1.id), python_journal) + self.assertSequenceEqual( Publication.objects.filter(article__headline__startswith="NASA"), - [ - '', - '', - '', - '', - '', - ]) + [self.p4, self.p2, self.p2, self.p3, self.p1], + ) - self.assertQuerysetEqual(Publication.objects.filter(article__id__exact=self.a1.id), python_journal) - self.assertQuerysetEqual(Publication.objects.filter(article__pk=self.a1.id), python_journal) - self.assertQuerysetEqual(Publication.objects.filter(article=self.a1.id), python_journal) - self.assertQuerysetEqual(Publication.objects.filter(article=self.a1), python_journal) + self.assertSequenceEqual(Publication.objects.filter(article__id__exact=self.a1.id), python_journal) + self.assertSequenceEqual(Publication.objects.filter(article__pk=self.a1.id), python_journal) + self.assertSequenceEqual(Publication.objects.filter(article=self.a1.id), python_journal) + self.assertSequenceEqual(Publication.objects.filter(article=self.a1), python_journal) - self.assertQuerysetEqual( + self.assertSequenceEqual( Publication.objects.filter(article__in=[self.a1.id, self.a2.id]).distinct(), - [ - '', - '', - '', - '', - ]) - self.assertQuerysetEqual( + [self.p4, self.p2, self.p3, self.p1], + ) + self.assertSequenceEqual( Publication.objects.filter(article__in=[self.a1.id, self.a2]).distinct(), - [ - '', - '', - '', - '', - ]) - self.assertQuerysetEqual( + [self.p4, self.p2, self.p3, self.p1], + ) + self.assertSequenceEqual( Publication.objects.filter(article__in=[self.a1, self.a2]).distinct(), - [ - '', - '', - '', - '', - ]) + [self.p4, self.p2, self.p3, self.p1], + ) def test_delete(self): # If we delete a Publication, its Articles won't be able to access it. self.p1.delete() - self.assertQuerysetEqual( + self.assertSequenceEqual( Publication.objects.all(), - [ - '', - '', - '', - ] + [self.p4, self.p2, self.p3], ) - self.assertQuerysetEqual(self.a1.publications.all(), []) + self.assertSequenceEqual(self.a1.publications.all(), []) # If we delete an Article, its Publications won't be able to access it. self.a2.delete() - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.all(), - [ - '', - '', - '', - ] + [self.a1, self.a3, self.a4], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( self.p2.article_set.all(), - [ - '', - '', - ] + [self.a3, self.a4], ) def test_bulk_delete(self): # Bulk delete some Publications - references to deleted publications should go Publication.objects.filter(title__startswith='Science').delete() - self.assertQuerysetEqual( + self.assertSequenceEqual( Publication.objects.all(), - [ - '', - '', - ] + [self.p4, self.p1], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.all(), - [ - '', - '', - '', - '', - ] + [self.a1, self.a3, self.a2, self.a4], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( self.a2.publications.all(), - [ - '', - '', - ] + [self.p4, self.p1], ) # Bulk delete some articles - references to deleted objects should go q = Article.objects.filter(headline__startswith='Django') - self.assertQuerysetEqual(q, ['']) + self.assertSequenceEqual(q, [self.a1]) q.delete() # After the delete, the QuerySet cache needs to be cleared, # and the referenced objects should be gone - self.assertQuerysetEqual(q, []) - self.assertQuerysetEqual(self.p1.article_set.all(), ['']) + self.assertSequenceEqual(q, []) + self.assertSequenceEqual(self.p1.article_set.all(), [self.a2]) def test_remove(self): # Removing publication from an article: - self.assertQuerysetEqual( + self.assertSequenceEqual( self.p2.article_set.all(), - [ - '', - '', - '', - ] + [self.a3, self.a2, self.a4], ) self.a4.publications.remove(self.p2) - self.assertQuerysetEqual( + self.assertSequenceEqual( self.p2.article_set.all(), - [ - '', - '', - ] + [self.a3, self.a2], ) - self.assertQuerysetEqual(self.a4.publications.all(), []) + self.assertSequenceEqual(self.a4.publications.all(), []) # And from the other end self.p2.article_set.remove(self.a3) - self.assertQuerysetEqual(self.p2.article_set.all(), ['']) - self.assertQuerysetEqual(self.a3.publications.all(), []) + self.assertSequenceEqual(self.p2.article_set.all(), [self.a2]) + self.assertSequenceEqual(self.a3.publications.all(), []) def test_set(self): self.p2.article_set.set([self.a4, self.a3]) - self.assertQuerysetEqual( + self.assertSequenceEqual( self.p2.article_set.all(), - [ - '', - '', - ] + [self.a3, self.a4], ) - self.assertQuerysetEqual(self.a4.publications.all(), ['']) + self.assertSequenceEqual(self.a4.publications.all(), [self.p2]) self.a4.publications.set([self.p3.id]) - self.assertQuerysetEqual(self.p2.article_set.all(), ['']) - self.assertQuerysetEqual(self.a4.publications.all(), ['']) + self.assertSequenceEqual(self.p2.article_set.all(), [self.a3]) + self.assertSequenceEqual(self.a4.publications.all(), [self.p3]) self.p2.article_set.set([]) - self.assertQuerysetEqual(self.p2.article_set.all(), []) + self.assertSequenceEqual(self.p2.article_set.all(), []) self.a4.publications.set([]) - self.assertQuerysetEqual(self.a4.publications.all(), []) + self.assertSequenceEqual(self.a4.publications.all(), []) self.p2.article_set.set([self.a4, self.a3], clear=True) - self.assertQuerysetEqual( + self.assertSequenceEqual( self.p2.article_set.all(), - [ - '', - '', - ] + [self.a3, self.a4], ) - self.assertQuerysetEqual(self.a4.publications.all(), ['']) + self.assertSequenceEqual(self.a4.publications.all(), [self.p2]) self.a4.publications.set([self.p3.id], clear=True) - self.assertQuerysetEqual(self.p2.article_set.all(), ['']) - self.assertQuerysetEqual(self.a4.publications.all(), ['']) + self.assertSequenceEqual(self.p2.article_set.all(), [self.a3]) + self.assertSequenceEqual(self.a4.publications.all(), [self.p3]) self.p2.article_set.set([], clear=True) - self.assertQuerysetEqual(self.p2.article_set.all(), []) + self.assertSequenceEqual(self.p2.article_set.all(), []) self.a4.publications.set([], clear=True) - self.assertQuerysetEqual(self.a4.publications.all(), []) + self.assertSequenceEqual(self.a4.publications.all(), []) def test_set_existing_different_type(self): # Existing many-to-many relations remain the same for values provided @@ -502,37 +374,32 @@ class ManyToManyTests(TestCase): def test_assign(self): # Relation sets can be assigned using set(). self.p2.article_set.set([self.a4, self.a3]) - self.assertQuerysetEqual( - self.p2.article_set.all(), [ - '', - '', - ] + self.assertSequenceEqual( + self.p2.article_set.all(), + [self.a3, self.a4], ) - self.assertQuerysetEqual(self.a4.publications.all(), ['']) + self.assertSequenceEqual(self.a4.publications.all(), [self.p2]) self.a4.publications.set([self.p3.id]) - self.assertQuerysetEqual(self.p2.article_set.all(), ['']) - self.assertQuerysetEqual(self.a4.publications.all(), ['']) + self.assertSequenceEqual(self.p2.article_set.all(), [self.a3]) + self.assertSequenceEqual(self.a4.publications.all(), [self.p3]) # An alternate to calling clear() is to set an empty set. self.p2.article_set.set([]) - self.assertQuerysetEqual(self.p2.article_set.all(), []) + self.assertSequenceEqual(self.p2.article_set.all(), []) self.a4.publications.set([]) - self.assertQuerysetEqual(self.a4.publications.all(), []) + self.assertSequenceEqual(self.a4.publications.all(), []) def test_assign_ids(self): # Relation sets can also be set using primary key values self.p2.article_set.set([self.a4.id, self.a3.id]) - self.assertQuerysetEqual( + self.assertSequenceEqual( self.p2.article_set.all(), - [ - '', - '', - ] + [self.a3, self.a4], ) - self.assertQuerysetEqual(self.a4.publications.all(), ['']) + self.assertSequenceEqual(self.a4.publications.all(), [self.p2]) self.a4.publications.set([self.p3.id]) - self.assertQuerysetEqual(self.p2.article_set.all(), ['']) - self.assertQuerysetEqual(self.a4.publications.all(), ['']) + self.assertSequenceEqual(self.p2.article_set.all(), [self.a3]) + self.assertSequenceEqual(self.a4.publications.all(), [self.p3]) def test_forward_assign_with_queryset(self): # Querysets used in m2m assignments are pre-evaluated so their value @@ -561,34 +428,31 @@ class ManyToManyTests(TestCase): def test_clear(self): # Relation sets can be cleared: self.p2.article_set.clear() - self.assertQuerysetEqual(self.p2.article_set.all(), []) - self.assertQuerysetEqual(self.a4.publications.all(), []) + self.assertSequenceEqual(self.p2.article_set.all(), []) + self.assertSequenceEqual(self.a4.publications.all(), []) # And you can clear from the other end self.p2.article_set.add(self.a3, self.a4) - self.assertQuerysetEqual( + self.assertSequenceEqual( self.p2.article_set.all(), - [ - '', - '', - ] + [self.a3, self.a4], ) - self.assertQuerysetEqual(self.a4.publications.all(), ['']) + self.assertSequenceEqual(self.a4.publications.all(), [self.p2]) self.a4.publications.clear() - self.assertQuerysetEqual(self.a4.publications.all(), []) - self.assertQuerysetEqual(self.p2.article_set.all(), ['']) + self.assertSequenceEqual(self.a4.publications.all(), []) + self.assertSequenceEqual(self.p2.article_set.all(), [self.a3]) def test_clear_after_prefetch(self): a4 = Article.objects.prefetch_related('publications').get(id=self.a4.id) - self.assertQuerysetEqual(a4.publications.all(), ['']) + self.assertSequenceEqual(a4.publications.all(), [self.p2]) a4.publications.clear() - self.assertQuerysetEqual(a4.publications.all(), []) + self.assertSequenceEqual(a4.publications.all(), []) def test_remove_after_prefetch(self): a4 = Article.objects.prefetch_related('publications').get(id=self.a4.id) - self.assertQuerysetEqual(a4.publications.all(), ['']) + self.assertSequenceEqual(a4.publications.all(), [self.p2]) a4.publications.remove(self.p2) - self.assertQuerysetEqual(a4.publications.all(), []) + self.assertSequenceEqual(a4.publications.all(), []) def test_add_after_prefetch(self): a4 = Article.objects.prefetch_related('publications').get(id=self.a4.id) @@ -610,7 +474,7 @@ class ManyToManyTests(TestCase): a4.publications.add(self.p1) self.assertEqual(a4.publications.count(), 2) a4.publications.remove(self.p1) - self.assertQuerysetEqual(a4.publications.all(), ['']) + self.assertSequenceEqual(a4.publications.all(), [self.p2]) def test_inherited_models_selects(self): """ @@ -620,22 +484,17 @@ class ManyToManyTests(TestCase): a = InheritedArticleA.objects.create() b = InheritedArticleB.objects.create() a.publications.add(self.p1, self.p2) - self.assertQuerysetEqual( + self.assertSequenceEqual( a.publications.all(), - [ - '', - '', - ]) - self.assertQuerysetEqual(b.publications.all(), []) - b.publications.add(self.p3) - self.assertQuerysetEqual( - a.publications.all(), - [ - '', - '', - ] + [self.p2, self.p1], ) - self.assertQuerysetEqual(b.publications.all(), ['']) + self.assertSequenceEqual(b.publications.all(), []) + b.publications.add(self.p3) + self.assertSequenceEqual( + a.publications.all(), + [self.p2, self.p1], + ) + self.assertSequenceEqual(b.publications.all(), [self.p3]) def test_custom_default_manager_exists_count(self): a5 = Article.objects.create(headline='deleted') diff --git a/tests/many_to_one/tests.py b/tests/many_to_one/tests.py index e1bfa0dcf6d..0687133de49 100644 --- a/tests/many_to_one/tests.py +++ b/tests/many_to_one/tests.py @@ -57,23 +57,23 @@ class ManyToOneTests(TestCase): self.r.article_set.add(new_article2, bulk=False) self.assertEqual(new_article2.reporter.id, self.r.id) - self.assertQuerysetEqual( + self.assertSequenceEqual( self.r.article_set.all(), - ["", "", ""] + [new_article, new_article2, self.a], ) # Add the same article to a different article set - check that it moves. self.r2.article_set.add(new_article2) self.assertEqual(new_article2.reporter.id, self.r2.id) - self.assertQuerysetEqual(self.r2.article_set.all(), [""]) + self.assertSequenceEqual(self.r2.article_set.all(), [new_article2]) # Adding an object of the wrong type raises TypeError. with transaction.atomic(): with self.assertRaisesMessage(TypeError, "'Article' instance expected, got ", ""] + [new_article, self.a], ) def test_set(self): @@ -85,29 +85,28 @@ class ManyToOneTests(TestCase): new_article2.save() self.assertEqual(repr(new_article2.reporter), "") self.assertEqual(new_article2.reporter.id, self.r.id) - self.assertQuerysetEqual(self.r.article_set.all(), [ - "", - "", - "", - ]) - self.assertQuerysetEqual(self.r2.article_set.all(), []) + self.assertSequenceEqual( + self.r.article_set.all(), + [new_article, new_article2, self.a], + ) + self.assertSequenceEqual(self.r2.article_set.all(), []) # Set the article back again. self.r2.article_set.set([new_article, new_article2]) - self.assertQuerysetEqual(self.r.article_set.all(), [""]) - self.assertQuerysetEqual( + self.assertSequenceEqual(self.r.article_set.all(), [self.a]) + self.assertSequenceEqual( self.r2.article_set.all(), - ["", ""] + [new_article, new_article2], ) # Funny case - because the ForeignKey cannot be null, # existing members of the set must remain. self.r.article_set.set([new_article]) - self.assertQuerysetEqual( + self.assertSequenceEqual( self.r.article_set.all(), - ["", ""] + [new_article, self.a], ) - self.assertQuerysetEqual(self.r2.article_set.all(), [""]) + self.assertSequenceEqual(self.r2.article_set.all(), [new_article2]) def test_reverse_assignment_deprecation(self): msg = ( @@ -126,29 +125,28 @@ class ManyToOneTests(TestCase): new_article2.save() self.assertEqual(repr(new_article2.reporter), "") self.assertEqual(new_article2.reporter.id, self.r.id) - self.assertQuerysetEqual(self.r.article_set.all(), [ - "", - "", - "", - ]) - self.assertQuerysetEqual(self.r2.article_set.all(), []) + self.assertSequenceEqual( + self.r.article_set.all(), + [new_article, new_article2, self.a], + ) + self.assertSequenceEqual(self.r2.article_set.all(), []) # Set the article back again using set() method. self.r2.article_set.set([new_article, new_article2]) - self.assertQuerysetEqual(self.r.article_set.all(), [""]) - self.assertQuerysetEqual( + self.assertSequenceEqual(self.r.article_set.all(), [self.a]) + self.assertSequenceEqual( self.r2.article_set.all(), - ["", ""] + [new_article, new_article2], ) # Because the ForeignKey cannot be null, existing members of the set # must remain. self.r.article_set.set([new_article]) - self.assertQuerysetEqual( + self.assertSequenceEqual( self.r.article_set.all(), - ["", ""] + [new_article, self.a], ) - self.assertQuerysetEqual(self.r2.article_set.all(), [""]) + self.assertSequenceEqual(self.r2.article_set.all(), [new_article2]) # Reporter cannot be null - there should not be a clear or remove method self.assertFalse(hasattr(self.r2.article_set, 'remove')) self.assertFalse(hasattr(self.r2.article_set, 'clear')) @@ -182,38 +180,44 @@ class ManyToOneTests(TestCase): self.assertTrue(Parent.bestchild.is_cached(parent)) def test_selects(self): - self.r.article_set.create(headline="John's second story", pub_date=datetime.date(2005, 7, 29)) - self.r2.article_set.create(headline="Paul's story", pub_date=datetime.date(2006, 1, 17)) + new_article1 = self.r.article_set.create( + headline="John's second story", + pub_date=datetime.date(2005, 7, 29), + ) + new_article2 = self.r2.article_set.create( + headline="Paul's story", + pub_date=datetime.date(2006, 1, 17), + ) # Reporter objects have access to their related Article objects. - self.assertQuerysetEqual(self.r.article_set.all(), [ - "", - "", - ]) - self.assertQuerysetEqual(self.r.article_set.filter(headline__startswith='This'), [""]) + self.assertSequenceEqual( + self.r.article_set.all(), + [new_article1, self.a], + ) + self.assertSequenceEqual(self.r.article_set.filter(headline__startswith='This'), [self.a]) self.assertEqual(self.r.article_set.count(), 2) self.assertEqual(self.r2.article_set.count(), 1) # Get articles by id - self.assertQuerysetEqual(Article.objects.filter(id__exact=self.a.id), [""]) - self.assertQuerysetEqual(Article.objects.filter(pk=self.a.id), [""]) + self.assertSequenceEqual(Article.objects.filter(id__exact=self.a.id), [self.a]) + self.assertSequenceEqual(Article.objects.filter(pk=self.a.id), [self.a]) # Query on an article property - self.assertQuerysetEqual(Article.objects.filter(headline__startswith='This'), [""]) + self.assertSequenceEqual(Article.objects.filter(headline__startswith='This'), [self.a]) # The API automatically follows relationships as far as you need. # Use double underscores to separate relationships. # This works as many levels deep as you want. There's no limit. # Find all Articles for any Reporter whose first name is "John". - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(reporter__first_name__exact='John'), - ["", ""] + [new_article1, self.a], ) # Implied __exact also works - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(reporter__first_name='John'), - ["", ""] + [new_article1, self.a], ) # Query twice over the related field. - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(reporter__first_name__exact='John', reporter__last_name__exact='Smith'), - ["", ""] + [new_article1, self.a], ) # The underlying query only makes one join when a related table is referenced twice. queryset = Article.objects.filter(reporter__first_name__exact='John', reporter__last_name__exact='Smith') @@ -221,69 +225,53 @@ class ManyToOneTests(TestCase): self.assertEqual(queryset.query.get_compiler(queryset.db).as_sql()[0].count('INNER JOIN'), 1) # The automatically joined table has a predictable name. - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(reporter__first_name__exact='John').extra( where=["many_to_one_reporter.last_name='Smith'"]), - ["", ""] + [new_article1, self.a], ) # ... and should work fine with the string that comes out of forms.Form.cleaned_data self.assertQuerysetEqual( (Article.objects .filter(reporter__first_name__exact='John') .extra(where=["many_to_one_reporter.last_name='%s'" % 'Smith'])), - ["", ""] + [new_article1, self.a] ) # Find all Articles for a Reporter. # Use direct ID check, pk check, and object comparison - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(reporter__id__exact=self.r.id), - [ - "", - "", - ]) - self.assertQuerysetEqual( + [new_article1, self.a], + ) + self.assertSequenceEqual( Article.objects.filter(reporter__pk=self.r.id), - [ - "", - "", - ]) - self.assertQuerysetEqual( + [new_article1, self.a], + ) + self.assertSequenceEqual( Article.objects.filter(reporter=self.r.id), - [ - "", - "", - ]) - self.assertQuerysetEqual( + [new_article1, self.a], + ) + self.assertSequenceEqual( Article.objects.filter(reporter=self.r), - [ - "", - "", - ]) - self.assertQuerysetEqual( + [new_article1, self.a], + ) + self.assertSequenceEqual( Article.objects.filter(reporter__in=[self.r.id, self.r2.id]).distinct(), - [ - "", - "", - "", - ]) - self.assertQuerysetEqual( + [new_article1, new_article2, self.a], + ) + self.assertSequenceEqual( Article.objects.filter(reporter__in=[self.r, self.r2]).distinct(), - [ - "", - "", - "", - ]) + [new_article1, new_article2, self.a], + ) # You can also use a queryset instead of a literal list of instances. # The queryset must be reduced to a list of values using values(), # then converted into a query - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter( reporter__in=Reporter.objects.filter(first_name='John').values('pk').query ).distinct(), - [ - "", - "", - ]) + [new_article1, self.a], + ) def test_reverse_selects(self): a3 = Article.objects.create( @@ -296,48 +284,42 @@ class ManyToOneTests(TestCase): pub_date=datetime.date(2005, 7, 27), reporter_id=self.r.id, ) - john_smith = [""] + john_smith = [self.r] # Reporters can be queried - self.assertQuerysetEqual(Reporter.objects.filter(id__exact=self.r.id), john_smith) - self.assertQuerysetEqual(Reporter.objects.filter(pk=self.r.id), john_smith) - self.assertQuerysetEqual(Reporter.objects.filter(first_name__startswith='John'), john_smith) + self.assertSequenceEqual(Reporter.objects.filter(id__exact=self.r.id), john_smith) + self.assertSequenceEqual(Reporter.objects.filter(pk=self.r.id), john_smith) + self.assertSequenceEqual(Reporter.objects.filter(first_name__startswith='John'), john_smith) # Reporters can query in opposite direction of ForeignKey definition - self.assertQuerysetEqual(Reporter.objects.filter(article__id__exact=self.a.id), john_smith) - self.assertQuerysetEqual(Reporter.objects.filter(article__pk=self.a.id), john_smith) - self.assertQuerysetEqual(Reporter.objects.filter(article=self.a.id), john_smith) - self.assertQuerysetEqual(Reporter.objects.filter(article=self.a), john_smith) - self.assertQuerysetEqual(Reporter.objects.filter(article__in=[self.a.id, a3.id]).distinct(), john_smith) - self.assertQuerysetEqual(Reporter.objects.filter(article__in=[self.a.id, a3]).distinct(), john_smith) - self.assertQuerysetEqual(Reporter.objects.filter(article__in=[self.a, a3]).distinct(), john_smith) - self.assertQuerysetEqual( + self.assertSequenceEqual(Reporter.objects.filter(article__id__exact=self.a.id), john_smith) + self.assertSequenceEqual(Reporter.objects.filter(article__pk=self.a.id), john_smith) + self.assertSequenceEqual(Reporter.objects.filter(article=self.a.id), john_smith) + self.assertSequenceEqual(Reporter.objects.filter(article=self.a), john_smith) + self.assertSequenceEqual(Reporter.objects.filter(article__in=[self.a.id, a3.id]).distinct(), john_smith) + self.assertSequenceEqual(Reporter.objects.filter(article__in=[self.a.id, a3]).distinct(), john_smith) + self.assertSequenceEqual(Reporter.objects.filter(article__in=[self.a, a3]).distinct(), john_smith) + self.assertCountEqual( Reporter.objects.filter(article__headline__startswith='T'), - ["", ""], - ordered=False + [self.r, self.r], ) - self.assertQuerysetEqual(Reporter.objects.filter(article__headline__startswith='T').distinct(), john_smith) + self.assertSequenceEqual(Reporter.objects.filter(article__headline__startswith='T').distinct(), john_smith) # Counting in the opposite direction works in conjunction with distinct() self.assertEqual(Reporter.objects.filter(article__headline__startswith='T').count(), 2) self.assertEqual(Reporter.objects.filter(article__headline__startswith='T').distinct().count(), 1) # Queries can go round in circles. - self.assertQuerysetEqual( + self.assertCountEqual( Reporter.objects.filter(article__reporter__first_name__startswith='John'), - [ - "", - "", - "", - ], - ordered=False + [self.r, self.r, self.r], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Reporter.objects.filter(article__reporter__first_name__startswith='John').distinct(), john_smith ) - self.assertQuerysetEqual(Reporter.objects.filter(article__reporter__exact=self.r).distinct(), john_smith) + self.assertSequenceEqual(Reporter.objects.filter(article__reporter__exact=self.r).distinct(), john_smith) # Implied __exact also works. - self.assertQuerysetEqual(Reporter.objects.filter(article__reporter=self.r).distinct(), john_smith) + self.assertSequenceEqual(Reporter.objects.filter(article__reporter=self.r).distinct(), john_smith) # It's possible to use values() calls across many-to-one relations. # (Note, too, that we clear the ordering here so as not to drag the @@ -370,44 +352,43 @@ class ManyToOneTests(TestCase): ) def test_delete(self): - self.r.article_set.create(headline="John's second story", pub_date=datetime.date(2005, 7, 29)) - self.r2.article_set.create(headline="Paul's story", pub_date=datetime.date(2006, 1, 17)) - Article.objects.create(headline="Third article", pub_date=datetime.date(2005, 7, 27), reporter_id=self.r.id) - Article.objects.create( + new_article1 = self.r.article_set.create( + headline="John's second story", + pub_date=datetime.date(2005, 7, 29), + ) + new_article2 = self.r2.article_set.create( + headline="Paul's story", + pub_date=datetime.date(2006, 1, 17), + ) + new_article3 = Article.objects.create( + headline="Third article", + pub_date=datetime.date(2005, 7, 27), + reporter_id=self.r.id, + ) + new_article4 = Article.objects.create( headline="Fourth article", pub_date=datetime.date(2005, 7, 27), reporter_id=str(self.r.id), ) # If you delete a reporter, his articles will be deleted. - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.all(), - [ - "", - "", - "", - "", - "", - ] + [new_article4, new_article1, new_article2, new_article3, self.a], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Reporter.objects.order_by('first_name'), - ["", ""] + [self.r, self.r2], ) self.r2.delete() - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.all(), - [ - "", - "", - "", - "", - ] + [new_article4, new_article1, new_article3, self.a], ) - self.assertQuerysetEqual(Reporter.objects.order_by('first_name'), [""]) + self.assertSequenceEqual(Reporter.objects.order_by('first_name'), [self.r]) # You can delete using a JOIN in the query. Reporter.objects.filter(article__headline__startswith='This').delete() - self.assertQuerysetEqual(Reporter.objects.all(), []) - self.assertQuerysetEqual(Article.objects.all(), []) + self.assertSequenceEqual(Reporter.objects.all(), []) + self.assertSequenceEqual(Article.objects.all(), []) def test_explicit_fk(self): # Create a new Article with get_or_create using an explicit value @@ -421,9 +402,9 @@ class ManyToOneTests(TestCase): self.assertEqual(a2.reporter.id, self.r.id) # You can specify filters containing the explicit FK value. - self.assertQuerysetEqual( + self.assertSequenceEqual( Article.objects.filter(reporter_id__exact=self.r.id), - ["", ""] + [a2, self.a], ) # Create an Article by Paul for the same date. @@ -598,15 +579,15 @@ class ManyToOneTests(TestCase): r5 = Record.objects.create(category=c3) Relation.objects.create(left=r1, right=r2) Relation.objects.create(left=r3, right=r4) - Relation.objects.create(left=r1, right=r3) + rel = Relation.objects.create(left=r1, right=r3) Relation.objects.create(left=r5, right=r2) Relation.objects.create(left=r3, right=r2) q1 = Relation.objects.filter(left__category__name__in=['First'], right__category__name__in=['Second']) - self.assertQuerysetEqual(q1, [""]) + self.assertSequenceEqual(q1, [rel]) q2 = Category.objects.filter(record__left_set__right__category__name='Second').order_by('name') - self.assertQuerysetEqual(q2, ["", ""]) + self.assertSequenceEqual(q2, [c1, c2]) p = Parent.objects.create(name="Parent") c = Child.objects.create(name="Child", parent=p) @@ -669,19 +650,19 @@ class ManyToOneTests(TestCase): def test_clear_after_prefetch(self): c = City.objects.create(name='Musical City') - District.objects.create(name='Ladida', city=c) + d = District.objects.create(name='Ladida', city=c) city = City.objects.prefetch_related('districts').get(id=c.id) - self.assertQuerysetEqual(city.districts.all(), ['']) + self.assertSequenceEqual(city.districts.all(), [d]) city.districts.clear() - self.assertQuerysetEqual(city.districts.all(), []) + self.assertSequenceEqual(city.districts.all(), []) def test_remove_after_prefetch(self): c = City.objects.create(name='Musical City') d = District.objects.create(name='Ladida', city=c) city = City.objects.prefetch_related('districts').get(id=c.id) - self.assertQuerysetEqual(city.districts.all(), ['']) + self.assertSequenceEqual(city.districts.all(), [d]) city.districts.remove(d) - self.assertQuerysetEqual(city.districts.all(), []) + self.assertSequenceEqual(city.districts.all(), []) def test_add_after_prefetch(self): c = City.objects.create(name='Musical City') @@ -699,7 +680,7 @@ class ManyToOneTests(TestCase): city = City.objects.prefetch_related('districts').get(id=c.id) self.assertEqual(city.districts.count(), 1) city.districts.set([d2]) - self.assertQuerysetEqual(city.districts.all(), ['']) + self.assertSequenceEqual(city.districts.all(), [d2]) def test_add_then_remove_after_prefetch(self): c = City.objects.create(name='Musical City') diff --git a/tests/many_to_one_null/tests.py b/tests/many_to_one_null/tests.py index 401e41b447b..d27143bf004 100644 --- a/tests/many_to_one_null/tests.py +++ b/tests/many_to_one_null/tests.py @@ -33,8 +33,8 @@ class ManyToOneNullTests(TestCase): def test_related_set(self): # Reporter objects have access to their related Article objects. - self.assertQuerysetEqual(self.r.article_set.all(), ['', '']) - self.assertQuerysetEqual(self.r.article_set.filter(headline__startswith='Fir'), ['']) + self.assertSequenceEqual(self.r.article_set.all(), [self.a, self.a2]) + self.assertSequenceEqual(self.r.article_set.filter(headline__startswith='Fir'), [self.a]) self.assertEqual(self.r.article_set.count(), 2) def test_created_without_related(self): @@ -47,43 +47,43 @@ class ManyToOneNullTests(TestCase): # if the reporter is set to None. self.assertIsNone(a3.reporter) # To retrieve the articles with no reporters set, use "reporter__isnull=True". - self.assertQuerysetEqual(Article.objects.filter(reporter__isnull=True), ['']) + self.assertSequenceEqual(Article.objects.filter(reporter__isnull=True), [self.a3]) # We can achieve the same thing by filtering for the case where the # reporter is None. - self.assertQuerysetEqual(Article.objects.filter(reporter=None), ['']) + self.assertSequenceEqual(Article.objects.filter(reporter=None), [self.a3]) # Set the reporter for the Third article - self.assertQuerysetEqual(self.r.article_set.all(), ['', '']) + self.assertSequenceEqual(self.r.article_set.all(), [self.a, self.a2]) self.r.article_set.add(a3) - self.assertQuerysetEqual( + self.assertSequenceEqual( self.r.article_set.all(), - ['', '', ''] + [self.a, self.a2, self.a3], ) # Remove an article from the set, and check that it was removed. self.r.article_set.remove(a3) - self.assertQuerysetEqual(self.r.article_set.all(), ['', '']) - self.assertQuerysetEqual(Article.objects.filter(reporter__isnull=True), ['']) + self.assertSequenceEqual(self.r.article_set.all(), [self.a, self.a2]) + self.assertSequenceEqual(Article.objects.filter(reporter__isnull=True), [self.a3]) def test_remove_from_wrong_set(self): - self.assertQuerysetEqual(self.r2.article_set.all(), ['']) + self.assertSequenceEqual(self.r2.article_set.all(), [self.a4]) # Try to remove a4 from a set it does not belong to with self.assertRaises(Reporter.DoesNotExist): self.r.article_set.remove(self.a4) - self.assertQuerysetEqual(self.r2.article_set.all(), ['']) + self.assertSequenceEqual(self.r2.article_set.all(), [self.a4]) def test_set(self): # Use manager.set() to allocate ForeignKey. Null is legal, so existing # members of the set that are not in the assignment set are set to null. self.r2.article_set.set([self.a2, self.a3]) - self.assertQuerysetEqual(self.r2.article_set.all(), ['', '']) + self.assertSequenceEqual(self.r2.article_set.all(), [self.a2, self.a3]) # Use manager.set(clear=True) self.r2.article_set.set([self.a3, self.a4], clear=True) - self.assertQuerysetEqual(self.r2.article_set.all(), ['', '']) + self.assertSequenceEqual(self.r2.article_set.all(), [self.a4, self.a3]) # Clear the rest of the set self.r2.article_set.set([]) - self.assertQuerysetEqual(self.r2.article_set.all(), []) - self.assertQuerysetEqual( + self.assertSequenceEqual(self.r2.article_set.all(), []) + self.assertSequenceEqual( Article.objects.filter(reporter__isnull=True), - ['', '', ''] + [self.a4, self.a2, self.a3], ) def test_set_clear_non_bulk(self): @@ -96,13 +96,13 @@ class ManyToOneNullTests(TestCase): # existing members of the set that are not in the assignment set are # set to null. self.r2.article_set.set([self.a2, self.a3]) - self.assertQuerysetEqual(self.r2.article_set.all(), ['', '']) + self.assertSequenceEqual(self.r2.article_set.all(), [self.a2, self.a3]) # Clear the rest of the set self.r.article_set.clear() - self.assertQuerysetEqual(self.r.article_set.all(), []) - self.assertQuerysetEqual( + self.assertSequenceEqual(self.r.article_set.all(), []) + self.assertSequenceEqual( Article.objects.filter(reporter__isnull=True), - ['', ''] + [self.a, self.a4], ) def test_assign_with_queryset(self): diff --git a/tests/model_fields/test_datetimefield.py b/tests/model_fields/test_datetimefield.py index ea759e08c63..1c37760711e 100644 --- a/tests/model_fields/test_datetimefield.py +++ b/tests/model_fields/test_datetimefield.py @@ -59,14 +59,13 @@ class DateTimeFieldTests(TestCase): m1 = DateTimeModel.objects.create(d=d, dt=dt1, t=t) m2 = DateTimeModel.objects.create(d=d, dt=dt2, t=t) # In Vancouver, we expect both results. - self.assertQuerysetEqual( + self.assertCountEqual( DateTimeModel.objects.filter(dt__date=d), - [repr(m1), repr(m2)], - ordered=False + [m1, m2], ) with self.settings(TIME_ZONE='UTC'): # But in UTC, the __date only matches one of them. - self.assertQuerysetEqual(DateTimeModel.objects.filter(dt__date=d), [repr(m1)]) + self.assertCountEqual(DateTimeModel.objects.filter(dt__date=d), [m1]) class ValidationTest(SimpleTestCase): diff --git a/tests/model_forms/tests.py b/tests/model_forms/tests.py index d7bd768e7bd..9931fa50e3b 100644 --- a/tests/model_forms/tests.py +++ b/tests/model_forms/tests.py @@ -1444,7 +1444,7 @@ class ModelFormBasicTests(TestCase): article="Hello.", headline="New headline", slug="new-headline", pub_date=datetime.date(1988, 1, 4), writer=self.w_royko) new_art.categories.add(Category.objects.get(name='Entertainment')) - self.assertQuerysetEqual(new_art.categories.all(), ["Entertainment"]) + self.assertSequenceEqual(new_art.categories.all(), [self.c1]) f = ArticleForm(auto_id=False, instance=new_art) self.assertHTMLEqual( f.as_ul(), @@ -1528,7 +1528,7 @@ class ModelFormBasicTests(TestCase): new_art = f.save() new_art = Article.objects.get(id=new_art.id) art_id_1 = new_art.id - self.assertQuerysetEqual(new_art.categories.order_by('name'), ["Entertainment", "It's a test"]) + self.assertSequenceEqual(new_art.categories.order_by('name'), [self.c1, self.c2]) # Now, submit form data with no categories. This deletes the existing categories. form_data['categories'] = [] @@ -1536,7 +1536,7 @@ class ModelFormBasicTests(TestCase): new_art = f.save() self.assertEqual(new_art.id, art_id_1) new_art = Article.objects.get(id=art_id_1) - self.assertQuerysetEqual(new_art.categories.all(), []) + self.assertSequenceEqual(new_art.categories.all(), []) # Create a new article, with no categories, via the form. f = ArticleForm(form_data) @@ -1544,7 +1544,7 @@ class ModelFormBasicTests(TestCase): art_id_2 = new_art.id self.assertNotIn(art_id_2, (None, art_id_1)) new_art = Article.objects.get(id=art_id_2) - self.assertQuerysetEqual(new_art.categories.all(), []) + self.assertSequenceEqual(new_art.categories.all(), []) # Create a new article, with categories, via the form, but use commit=False. # The m2m data won't be saved until save_m2m() is invoked on the form. @@ -1559,11 +1559,11 @@ class ModelFormBasicTests(TestCase): # The instance doesn't have m2m data yet new_art = Article.objects.get(id=art_id_3) - self.assertQuerysetEqual(new_art.categories.all(), []) + self.assertSequenceEqual(new_art.categories.all(), []) # Save the m2m data on the form f.save_m2m() - self.assertQuerysetEqual(new_art.categories.order_by('name'), ["Entertainment", "It's a test"]) + self.assertSequenceEqual(new_art.categories.order_by('name'), [self.c1, self.c2]) def test_custom_form_fields(self): # Here, we define a custom ModelForm. Because it happens to have the same fields as @@ -1720,20 +1720,20 @@ class ModelMultipleChoiceFieldTests(TestCase): f.clean(None) with self.assertRaises(ValidationError): f.clean([]) - self.assertQuerysetEqual(f.clean([self.c1.id]), ["Entertainment"]) - self.assertQuerysetEqual(f.clean([self.c2.id]), ["It's a test"]) - self.assertQuerysetEqual(f.clean([str(self.c1.id)]), ["Entertainment"]) - self.assertQuerysetEqual( + self.assertCountEqual(f.clean([self.c1.id]), [self.c1]) + self.assertCountEqual(f.clean([self.c2.id]), [self.c2]) + self.assertCountEqual(f.clean([str(self.c1.id)]), [self.c1]) + self.assertCountEqual( f.clean([str(self.c1.id), str(self.c2.id)]), - ["Entertainment", "It's a test"], ordered=False + [self.c1, self.c2], ) - self.assertQuerysetEqual( + self.assertCountEqual( f.clean([self.c1.id, str(self.c2.id)]), - ["Entertainment", "It's a test"], ordered=False + [self.c1, self.c2], ) - self.assertQuerysetEqual( + self.assertCountEqual( f.clean((self.c1.id, str(self.c2.id))), - ["Entertainment", "It's a test"], ordered=False + [self.c1, self.c2], ) with self.assertRaises(ValidationError): f.clean(['100']) @@ -1755,7 +1755,7 @@ class ModelMultipleChoiceFieldTests(TestCase): # this may create categories with primary keys up to 6. Use # a number that will not conflict. c6 = Category.objects.create(id=1006, name='Sixth', url='6th') - self.assertQuerysetEqual(f.clean([c6.id]), ["Sixth"]) + self.assertCountEqual(f.clean([c6.id]), [c6]) # Delete a Category object *after* the ModelMultipleChoiceField has already been # instantiated. This proves clean() checks the database during clean() rather @@ -1780,7 +1780,7 @@ class ModelMultipleChoiceFieldTests(TestCase): self.assertEqual(list(f.choices), [ (self.c1.pk, 'Entertainment'), (self.c2.pk, "It's a test")]) - self.assertQuerysetEqual(f.clean([self.c2.id]), ["It's a test"]) + self.assertSequenceEqual(f.clean([self.c2.id]), [self.c2]) with self.assertRaises(ValidationError): f.clean([self.c3.id]) with self.assertRaises(ValidationError): @@ -2512,7 +2512,7 @@ class OtherModelFormTests(TestCase): def test_foreignkeys_which_use_to_field(self): apple = Inventory.objects.create(barcode=86, name='Apple') - Inventory.objects.create(barcode=22, name='Pear') + pear = Inventory.objects.create(barcode=22, name='Pear') core = Inventory.objects.create(barcode=87, name='Core', parent=apple) field = forms.ModelChoiceField(Inventory.objects.all(), to_field_name='barcode') @@ -2555,12 +2555,12 @@ class OtherModelFormTests(TestCase): field = forms.ModelMultipleChoiceField(Inventory.objects.all(), to_field_name='barcode') self.assertEqual(tuple(field.choices), ((86, 'Apple'), (87, 'Core'), (22, 'Pear'))) - self.assertQuerysetEqual(field.clean([86]), ['Apple']) + self.assertSequenceEqual(field.clean([86]), [apple]) form = SelectInventoryForm({'items': [87, 22]}) self.assertTrue(form.is_valid()) self.assertEqual(len(form.cleaned_data), 1) - self.assertQuerysetEqual(form.cleaned_data['items'], ['Core', 'Pear']) + self.assertSequenceEqual(form.cleaned_data['items'], [core, pear]) def test_model_field_that_returns_none_to_exclude_itself_with_explicit_fields(self): self.assertEqual(list(CustomFieldForExclusionForm.base_fields), ['name']) diff --git a/tests/model_formsets/tests.py b/tests/model_formsets/tests.py index 9c06d45339d..98fd501ad60 100644 --- a/tests/model_formsets/tests.py +++ b/tests/model_formsets/tests.py @@ -368,21 +368,19 @@ class ModelFormsetTest(TestCase): instance.created = date.today() instance.save() formset.save_m2m() - self.assertQuerysetEqual(instances[0].authors.all(), [ - '', - '', - '', - '', - ]) + self.assertSequenceEqual( + instances[0].authors.all(), + [author1, author4, author2, author3], + ) def test_max_num(self): # Test the behavior of max_num with model formsets. It should allow # all existing related objects/inlines for a given object to be # displayed, but not allow the creation of new inlines beyond max_num. - Author.objects.create(name='Charles Baudelaire') - Author.objects.create(name='Paul Verlaine') - Author.objects.create(name='Walt Whitman') + a1 = Author.objects.create(name='Charles Baudelaire') + a2 = Author.objects.create(name='Paul Verlaine') + a3 = Author.objects.create(name='Walt Whitman') qs = Author.objects.order_by('name') @@ -403,27 +401,15 @@ class ModelFormsetTest(TestCase): AuthorFormSet = modelformset_factory(Author, fields="__all__", max_num=None) formset = AuthorFormSet(queryset=qs) - self.assertQuerysetEqual(formset.get_queryset(), [ - '', - '', - '', - ]) + self.assertSequenceEqual(formset.get_queryset(), [a1, a2, a3]) AuthorFormSet = modelformset_factory(Author, fields="__all__", max_num=0) formset = AuthorFormSet(queryset=qs) - self.assertQuerysetEqual(formset.get_queryset(), [ - '', - '', - '', - ]) + self.assertSequenceEqual(formset.get_queryset(), [a1, a2, a3]) AuthorFormSet = modelformset_factory(Author, fields="__all__", max_num=4) formset = AuthorFormSet(queryset=qs) - self.assertQuerysetEqual(formset.get_queryset(), [ - '', - '', - '', - ]) + self.assertSequenceEqual(formset.get_queryset(), [a1, a2, a3]) def test_min_num(self): # Test the behavior of min_num with model formsets. It should be @@ -633,7 +619,7 @@ class ModelFormsetTest(TestCase): self.assertEqual(len(saved), 1) book1, = saved self.assertEqual(book1, Book.objects.get(title='Les Fleurs du Mal')) - self.assertQuerysetEqual(author.book_set.all(), ['']) + self.assertSequenceEqual(author.book_set.all(), [book1]) # Now that we've added a book to Charles Baudelaire, let's try adding # another one. This time though, an edit form will be available for @@ -689,10 +675,7 @@ class ModelFormsetTest(TestCase): # As you can see, 'Les Paradis Artificiels' is now a book belonging to # Charles Baudelaire. - self.assertQuerysetEqual(author.book_set.order_by('title'), [ - '', - '', - ]) + self.assertSequenceEqual(author.book_set.order_by('title'), [book1, book2]) def test_inline_formsets_save_as_new(self): # The save_as_new parameter lets you re-associate the data to a new @@ -1722,7 +1705,7 @@ class ModelFormsetTest(TestCase): formset.save() # The name of other_author shouldn't be changed and new models aren't # created. - self.assertQuerysetEqual(Author.objects.all(), ['', '']) + self.assertSequenceEqual(Author.objects.all(), [author, other_author]) def test_validation_without_id(self): AuthorFormSet = modelformset_factory(Author, fields='__all__') diff --git a/tests/model_formsets_regress/tests.py b/tests/model_formsets_regress/tests.py index 9f7bbff05ec..8e480b72664 100644 --- a/tests/model_formsets_regress/tests.py +++ b/tests/model_formsets_regress/tests.py @@ -246,7 +246,10 @@ class InlineFormsetTests(TestCase): formset.save() self.assertQuerysetEqual( dalnet.host_set.order_by("hostname"), - ["", ""] + Host.objects.filter(hostname__in=[ + 'matrix.de.eu.dal.net', + 'tranquility.hub.dal.net', + ]).order_by('hostname'), ) def test_initial_data(self): diff --git a/tests/one_to_one/tests.py b/tests/one_to_one/tests.py index bb3e5aebbfe..6100e53208b 100644 --- a/tests/one_to_one/tests.py +++ b/tests/one_to_one/tests.py @@ -46,15 +46,10 @@ class OneToOneTests(TestCase): def test_manager_all(self): # Restaurant.objects.all() just returns the Restaurants, not the Places. - self.assertQuerysetEqual(Restaurant.objects.all(), [ - '', - ]) + self.assertSequenceEqual(Restaurant.objects.all(), [self.r1]) # Place.objects.all() returns all Places, regardless of whether they # have Restaurants. - self.assertQuerysetEqual(Place.objects.order_by('name'), [ - '', - '', - ]) + self.assertSequenceEqual(Place.objects.order_by('name'), [self.p2, self.p1]) def test_manager_get(self): def assert_get_restaurant(**params): @@ -92,9 +87,7 @@ class OneToOneTests(TestCase): # Query the waiters def assert_filter_waiters(**params): - self.assertQuerysetEqual(Waiter.objects.filter(**params), [ - '' - ]) + self.assertSequenceEqual(Waiter.objects.filter(**params), [w]) assert_filter_waiters(restaurant__place__exact=self.p1.pk) assert_filter_waiters(restaurant__place__exact=self.p1) assert_filter_waiters(restaurant__place__pk=self.p1.pk) @@ -169,10 +162,7 @@ class OneToOneTests(TestCase): f = Favorites(name='Fred') f.save() f.restaurants.set([self.r1]) - self.assertQuerysetEqual( - f.restaurants.all(), - [''] - ) + self.assertSequenceEqual(f.restaurants.all(), [self.r1]) def test_reverse_object_cache(self): """ diff --git a/tests/pagination/tests.py b/tests/pagination/tests.py index d781bdf8a75..43e8c28046a 100644 --- a/tests/pagination/tests.py +++ b/tests/pagination/tests.py @@ -433,21 +433,17 @@ class ModelPaginationTests(TestCase): @classmethod def setUpTestData(cls): # Prepare a list of objects for pagination. - for x in range(1, 10): - a = Article(headline='Article %s' % x, pub_date=datetime(2005, 7, 29)) - a.save() + pub_date = datetime(2005, 7, 29) + cls.articles = [ + Article.objects.create(headline=f'Article {x}', pub_date=pub_date) + for x in range(1, 10) + ] def test_first_page(self): paginator = Paginator(Article.objects.order_by('id'), 5) p = paginator.page(1) self.assertEqual("", str(p)) - self.assertQuerysetEqual(p.object_list, [ - "", - "", - "", - "", - "" - ]) + self.assertSequenceEqual(p.object_list, self.articles[:5]) self.assertTrue(p.has_next()) self.assertFalse(p.has_previous()) self.assertTrue(p.has_other_pages()) @@ -461,12 +457,7 @@ class ModelPaginationTests(TestCase): paginator = Paginator(Article.objects.order_by('id'), 5) p = paginator.page(2) self.assertEqual("", str(p)) - self.assertQuerysetEqual(p.object_list, [ - "", - "", - "", - "" - ]) + self.assertSequenceEqual(p.object_list, self.articles[5:]) self.assertFalse(p.has_next()) self.assertTrue(p.has_previous()) self.assertTrue(p.has_other_pages()) @@ -494,12 +485,8 @@ class ModelPaginationTests(TestCase): self.assertNotIsInstance(p.object_list, list) # Make sure slicing the Page object with numbers and slice objects work. - self.assertEqual(p[0], Article.objects.get(headline='Article 1')) - self.assertQuerysetEqual(p[slice(2)], [ - "", - "", - ] - ) + self.assertEqual(p[0], self.articles[0]) + self.assertSequenceEqual(p[slice(2)], self.articles[:2]) # After __getitem__ is called, object_list is a list self.assertIsInstance(p.object_list, list) diff --git a/tests/prefetch_related/tests.py b/tests/prefetch_related/tests.py index c368e040eaf..e21bd5ec232 100644 --- a/tests/prefetch_related/tests.py +++ b/tests/prefetch_related/tests.py @@ -76,7 +76,7 @@ class PrefetchRelatedTests(TestDataMixin, TestCase): [list(b.first_time_authors.all()) for b in Book.objects.prefetch_related('first_time_authors')] - self.assertQuerysetEqual(self.book2.authors.all(), [""]) + self.assertSequenceEqual(self.book2.authors.all(), [self.author1]) def test_onetoone_reverse_no_match(self): # Regression for #17439 @@ -1580,4 +1580,4 @@ class ReadPrefetchedObjectsCacheTests(TestCase): ) with self.assertNumQueries(4): # AuthorWithAge -> Author -> FavoriteAuthors, Book - self.assertQuerysetEqual(authors, ['', '']) + self.assertSequenceEqual(authors, [self.author1, self.author2]) diff --git a/tests/queries/tests.py b/tests/queries/tests.py index c3e3a40340a..37ba2394192 100644 --- a/tests/queries/tests.py +++ b/tests/queries/tests.py @@ -38,20 +38,20 @@ from .models import ( class Queries1Tests(TestCase): @classmethod def setUpTestData(cls): - generic = NamedCategory.objects.create(name="Generic") + cls.nc1 = generic = NamedCategory.objects.create(name="Generic") cls.t1 = Tag.objects.create(name='t1', category=generic) cls.t2 = Tag.objects.create(name='t2', parent=cls.t1, category=generic) cls.t3 = Tag.objects.create(name='t3', parent=cls.t1) - t4 = Tag.objects.create(name='t4', parent=cls.t3) + cls.t4 = Tag.objects.create(name='t4', parent=cls.t3) cls.t5 = Tag.objects.create(name='t5', parent=cls.t3) cls.n1 = Note.objects.create(note='n1', misc='foo', id=1) cls.n2 = Note.objects.create(note='n2', misc='bar', id=2) cls.n3 = Note.objects.create(note='n3', misc='foo', id=3, negate=False) - ann1 = Annotation.objects.create(name='a1', tag=cls.t1) - ann1.notes.add(cls.n1) - ann2 = Annotation.objects.create(name='a2', tag=t4) + cls.ann1 = Annotation.objects.create(name='a1', tag=cls.t1) + cls.ann1.notes.add(cls.n1) + ann2 = Annotation.objects.create(name='a2', tag=cls.t4) ann2.notes.add(cls.n2, cls.n3) # Create these out of order so that sorting by 'id' will be different to sorting @@ -73,19 +73,19 @@ class Queries1Tests(TestCase): cls.i2 = Item.objects.create(name='two', created=cls.time2, creator=cls.a2, note=cls.n2) cls.i2.tags.set([cls.t1, cls.t3]) cls.i3 = Item.objects.create(name='three', created=time3, creator=cls.a2, note=cls.n3) - i4 = Item.objects.create(name='four', created=time4, creator=cls.a4, note=cls.n3) - i4.tags.set([t4]) + cls.i4 = Item.objects.create(name='four', created=time4, creator=cls.a4, note=cls.n3) + cls.i4.tags.set([cls.t4]) cls.r1 = Report.objects.create(name='r1', creator=cls.a1) - Report.objects.create(name='r2', creator=cls.a3) - Report.objects.create(name='r3') + cls.r2 = Report.objects.create(name='r2', creator=cls.a3) + cls.r3 = Report.objects.create(name='r3') # Ordering by 'rank' gives us rank2, rank1, rank3. Ordering by the Meta.ordering # will be rank3, rank2, rank1. cls.rank1 = Ranking.objects.create(rank=2, author=cls.a2) - Cover.objects.create(title="first", item=i4) - Cover.objects.create(title="second", item=cls.i2) + cls.c1 = Cover.objects.create(title="first", item=cls.i4) + cls.c2 = Cover.objects.create(title="second", item=cls.i2) def test_subquery_condition(self): qs1 = Tag.objects.filter(pk__lte=0) @@ -101,27 +101,27 @@ class Queries1Tests(TestCase): self.assertEqual(str(qs4.query).lower().count('u0.'), 4) def test_ticket1050(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(tags__isnull=True), - [''] + [self.i3], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(tags__id__isnull=True), - [''] + [self.i3], ) def test_ticket1801(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.filter(item=self.i2), - [''] + [self.a2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.filter(item=self.i3), - [''] + [self.a2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.filter(item=self.i2) & Author.objects.filter(item=self.i3), - [''] + [self.a2], ) def test_ticket2306(self): @@ -129,84 +129,84 @@ class Queries1Tests(TestCase): query = Item.objects.filter(tags=self.t2).query self.assertNotIn(LOUTER, [x.join_type for x in query.alias_map.values()]) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(Q(tags=self.t1)).order_by('name'), - ['', ''] + [self.i1, self.i2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(Q(tags=self.t1)).filter(Q(tags=self.t2)), - [''] + [self.i1], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(Q(tags=self.t1)).filter(Q(creator__name='fred') | Q(tags=self.t2)), - [''] + [self.i1], ) # Each filter call is processed "at once" against a single table, so this is # different from the previous example as it tries to find tags that are two # things at once (rather than two tags). - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(Q(tags=self.t1) & Q(tags=self.t2)), [] ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(Q(tags=self.t1), Q(creator__name='fred') | Q(tags=self.t2)), [] ) qs = Author.objects.filter(ranking__rank=2, ranking__id=self.rank1.id) - self.assertQuerysetEqual(list(qs), ['']) + self.assertSequenceEqual(list(qs), [self.a2]) self.assertEqual(2, qs.query.count_active_tables(), 2) qs = Author.objects.filter(ranking__rank=2).filter(ranking__id=self.rank1.id) self.assertEqual(qs.query.count_active_tables(), 3) def test_ticket4464(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(tags=self.t1).filter(tags=self.t2), - [''] + [self.i1], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(tags__in=[self.t1, self.t2]).distinct().order_by('name'), - ['', ''] + [self.i1, self.i2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(tags__in=[self.t1, self.t2]).filter(tags=self.t3), - [''] + [self.i2], ) # Make sure .distinct() works with slicing (this was broken in Oracle). - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(tags__in=[self.t1, self.t2]).order_by('name')[:3], - ['', '', ''] + [self.i1, self.i1, self.i2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(tags__in=[self.t1, self.t2]).distinct().order_by('name')[:3], - ['', ''] + [self.i1, self.i2], ) def test_tickets_2080_3592(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.filter(item__name='one') | Author.objects.filter(name='a3'), - ['', ''] + [self.a1, self.a3], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.filter(Q(item__name='one') | Q(name='a3')), - ['', ''] + [self.a1, self.a3], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.filter(Q(name='a3') | Q(item__name='one')), - ['', ''] + [self.a1, self.a3], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.filter(Q(item__name='three') | Q(report__name='r3')), - [''] + [self.a2], ) def test_ticket6074(self): # Merging two empty result sets shouldn't leave a queryset with no constraints # (which would match everything). - self.assertQuerysetEqual(Author.objects.filter(Q(id__in=[])), []) - self.assertQuerysetEqual( + self.assertSequenceEqual(Author.objects.filter(Q(id__in=[])), []) + self.assertSequenceEqual( Author.objects.filter(Q(id__in=[]) | Q(id__in=[])), [] ) @@ -252,23 +252,20 @@ class Queries1Tests(TestCase): def test_ticket2253(self): q1 = Item.objects.order_by('name') q2 = Item.objects.filter(id=self.i1.id) - self.assertQuerysetEqual( - q1, - ['', '', '', ''] - ) - self.assertQuerysetEqual(q2, ['']) - self.assertQuerysetEqual( + self.assertSequenceEqual(q1, [self.i4, self.i1, self.i3, self.i2]) + self.assertSequenceEqual(q2, [self.i1]) + self.assertSequenceEqual( (q1 | q2).order_by('name'), - ['', '', '', ''] + [self.i4, self.i1, self.i3, self.i2], ) - self.assertQuerysetEqual((q1 & q2).order_by('name'), ['']) + self.assertSequenceEqual((q1 & q2).order_by('name'), [self.i1]) q1 = Item.objects.filter(tags=self.t1) q2 = Item.objects.filter(note=self.n3, tags=self.t2) q3 = Item.objects.filter(creator=self.a4) - self.assertQuerysetEqual( + self.assertSequenceEqual( ((q1 & q2) | q3).order_by('name'), - ['', ''] + [self.i4, self.i1], ) def test_order_by_tables(self): @@ -299,60 +296,57 @@ class Queries1Tests(TestCase): self.assertNotIn('order by', captured_queries[0]['sql'].lower()) def test_tickets_4088_4306(self): - self.assertQuerysetEqual( - Report.objects.filter(creator=1001), - [''] - ) - self.assertQuerysetEqual( + self.assertSequenceEqual(Report.objects.filter(creator=1001), [self.r1]) + self.assertSequenceEqual( Report.objects.filter(creator__num=1001), - [''] + [self.r1] ) - self.assertQuerysetEqual(Report.objects.filter(creator__id=1001), []) - self.assertQuerysetEqual( + self.assertSequenceEqual(Report.objects.filter(creator__id=1001), []) + self.assertSequenceEqual( Report.objects.filter(creator__id=self.a1.id), - [''] + [self.r1] ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Report.objects.filter(creator__name='a1'), - [''] + [self.r1] ) def test_ticket4510(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.filter(report__name='r1'), - [''] + [self.a1], ) def test_ticket7378(self): - self.assertQuerysetEqual(self.a1.report_set.all(), ['']) + self.assertSequenceEqual(self.a1.report_set.all(), [self.r1]) def test_tickets_5324_6704(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(tags__name='t4'), - [''] + [self.i4], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.exclude(tags__name='t4').order_by('name').distinct(), - ['', '', ''] + [self.i1, self.i3, self.i2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.exclude(tags__name='t4').order_by('name').distinct().reverse(), - ['', '', ''] + [self.i2, self.i3, self.i1], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.exclude(item__name='one').distinct().order_by('name'), - ['', '', ''] + [self.a2, self.a3, self.a4], ) # Excluding across a m2m relation when there is more than one related # object associated was problematic. - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.exclude(tags__name='t1').order_by('name'), - ['', ''] + [self.i4, self.i3], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.exclude(tags__name='t1').exclude(tags__name='t4'), - [''] + [self.i3], ) # Excluding from a relation that cannot be NULL should not use outer joins. @@ -373,37 +367,34 @@ class Queries1Tests(TestCase): ) # The previous changes shouldn't affect nullable foreign key joins. - self.assertQuerysetEqual( + self.assertSequenceEqual( Tag.objects.filter(parent__isnull=True).order_by('name'), - [''] + [self.t1] ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Tag.objects.exclude(parent__isnull=True).order_by('name'), - ['', '', '', ''] + [self.t2, self.t3, self.t4, self.t5], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Tag.objects.exclude(Q(parent__name='t1') | Q(parent__isnull=True)).order_by('name'), - ['', ''] + [self.t4, self.t5], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Tag.objects.exclude(Q(parent__isnull=True) | Q(parent__name='t1')).order_by('name'), - ['', ''] + [self.t4, self.t5], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Tag.objects.exclude(Q(parent__parent__isnull=True)).order_by('name'), - ['', ''] + [self.t4, self.t5], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Tag.objects.filter(~Q(parent__parent__isnull=True)).order_by('name'), - ['', ''] + [self.t4, self.t5], ) def test_ticket2091(self): t = Tag.objects.get(name='t4') - self.assertQuerysetEqual( - Item.objects.filter(tags__in=[t]), - [''] - ) + self.assertSequenceEqual(Item.objects.filter(tags__in=[t]), [self.i4]) def test_avoid_infinite_loop_on_too_many_subqueries(self): x = Tag.objects.filter(pk=1) @@ -440,19 +431,19 @@ class Queries1Tests(TestCase): ) def test_ticket2400(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.filter(item__isnull=True), - [''] + [self.a3], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Tag.objects.filter(item__isnull=True), - [''] + [self.t5], ) def test_ticket2496(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.extra(tables=['queries_author']).select_related().order_by('name')[:1], - [''] + [self.i4], ) def test_error_raised_on_filter_with_dictionary(self): @@ -462,56 +453,47 @@ class Queries1Tests(TestCase): def test_tickets_2076_7256(self): # Ordering on related tables should be possible, even if the table is # not otherwise involved. - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.order_by('note__note', 'name'), - ['', '', '', ''] + [self.i2, self.i4, self.i1, self.i3], ) # Ordering on a related field should use the remote model's default # ordering as a final step. - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.order_by('extra', '-name'), - ['', '', '', ''] + [self.a2, self.a1, self.a4, self.a3], ) # Using remote model default ordering can span multiple models (in this # case, Cover is ordered by Item's default, which uses Note's default). - self.assertQuerysetEqual( - Cover.objects.all(), - ['', ''] - ) + self.assertSequenceEqual(Cover.objects.all(), [self.c1, self.c2]) # If the remote model does not have a default ordering, we order by its 'id' # field. - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.order_by('creator', 'name'), - ['', '', '', ''] + [self.i1, self.i3, self.i2, self.i4], ) # Ordering by a many-valued attribute (e.g. a many-to-many or reverse # ForeignKey) is legal, but the results might not make sense. That # isn't Django's problem. Garbage in, garbage out. - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(tags__isnull=False).order_by('tags', 'id'), - ['', '', '', '', ''] + [self.i1, self.i2, self.i1, self.i2, self.i4], ) # If we replace the default ordering, Django adjusts the required # tables automatically. Item normally requires a join with Note to do # the default ordering, but that isn't needed here. qs = Item.objects.order_by('name') - self.assertQuerysetEqual( - qs, - ['', '', '', ''] - ) + self.assertSequenceEqual(qs, [self.i4, self.i1, self.i3, self.i2]) self.assertEqual(len(qs.query.alias_map), 1) def test_tickets_2874_3002(self): qs = Item.objects.select_related().order_by('note__note', 'name') - self.assertQuerysetEqual( - qs, - ['', '', '', ''] - ) + self.assertQuerysetEqual(qs, [self.i2, self.i4, self.i1, self.i3]) # This is also a good select_related() test because there are multiple # Note entries in the SQL. The two Note items should be different. @@ -519,9 +501,9 @@ class Queries1Tests(TestCase): self.assertEqual(repr(qs[0].creator.extra.note), '') def test_ticket3037(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(Q(creator__name='a3', name='two') | Q(creator__name='a4', name='four')), - [''] + [self.i4], ) def test_tickets_5321_7070(self): @@ -550,29 +532,29 @@ class Queries1Tests(TestCase): def test_ticket6154(self): # Multiple filter statements are joined using "AND" all the time. - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.filter(id=self.a1.id).filter(Q(extra__note=self.n1) | Q(item__note=self.n3)), - [''] + [self.a1], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.filter(Q(extra__note=self.n1) | Q(item__note=self.n3)).filter(id=self.a1.id), - [''] + [self.a1], ) def test_ticket6981(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Tag.objects.select_related('parent').order_by('name'), - ['', '', '', '', ''] + [self.t1, self.t2, self.t3, self.t4, self.t5], ) def test_ticket9926(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Tag.objects.select_related("parent", "category").order_by('name'), - ['', '', '', '', ''] + [self.t1, self.t2, self.t3, self.t4, self.t5], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Tag.objects.select_related('parent', "parent__category").order_by('name'), - ['', '', '', '', ''] + [self.t1, self.t2, self.t3, self.t4, self.t5], ) def test_tickets_6180_6203(self): @@ -585,31 +567,31 @@ class Queries1Tests(TestCase): def test_tickets_7087_12242(self): # Dates with extra select columns - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.datetimes('created', 'day').extra(select={'a': 1}), - ['datetime.datetime(2007, 12, 19, 0, 0)', 'datetime.datetime(2007, 12, 20, 0, 0)'] + [datetime.datetime(2007, 12, 19, 0, 0), datetime.datetime(2007, 12, 20, 0, 0)], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.extra(select={'a': 1}).datetimes('created', 'day'), - ['datetime.datetime(2007, 12, 19, 0, 0)', 'datetime.datetime(2007, 12, 20, 0, 0)'] + [datetime.datetime(2007, 12, 19, 0, 0), datetime.datetime(2007, 12, 20, 0, 0)], ) name = "one" - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.datetimes('created', 'day').extra(where=['name=%s'], params=[name]), - ['datetime.datetime(2007, 12, 19, 0, 0)'] + [datetime.datetime(2007, 12, 19, 0, 0)], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.extra(where=['name=%s'], params=[name]).datetimes('created', 'day'), - ['datetime.datetime(2007, 12, 19, 0, 0)'] + [datetime.datetime(2007, 12, 19, 0, 0)], ) def test_ticket7155(self): # Nullable dates - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.datetimes('modified', 'day'), - ['datetime.datetime(2007, 12, 19, 0, 0)'] + [datetime.datetime(2007, 12, 19, 0, 0)], ) @ignore_warnings(category=RemovedInDjango40Warning) @@ -644,35 +626,35 @@ class Queries1Tests(TestCase): def test_ticket7096(self): # Make sure exclude() with multiple conditions continues to work. - self.assertQuerysetEqual( + self.assertSequenceEqual( Tag.objects.filter(parent=self.t1, name='t3').order_by('name'), - [''] + [self.t3], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Tag.objects.exclude(parent=self.t1, name='t3').order_by('name'), - ['', '', '', ''] + [self.t1, self.t2, self.t4, self.t5], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.exclude(tags__name='t1', name='one').order_by('name').distinct(), - ['', '', ''] + [self.i4, self.i3, self.i2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(name__in=['three', 'four']).exclude(tags__name='t1').order_by('name'), - ['', ''] + [self.i4, self.i3], ) # More twisted cases, involving nested negations. - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.exclude(~Q(tags__name='t1', name='one')), - [''] + [self.i1], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(~Q(tags__name='t1', name='one'), name='two'), - [''] + [self.i2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.exclude(~Q(tags__name='t1', name='one'), name='two'), - ['', '', ''] + [self.i4, self.i1, self.i3], ) def test_tickets_7204_7506(self): @@ -701,19 +683,19 @@ class Queries1Tests(TestCase): self.assertEqual(list(qs), list(q3)) def test_ticket7277(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( self.n1.annotation_set.filter( Q(tag=self.t5) | Q(tag__children=self.t5) | Q(tag__children__children=self.t5) ), - [''] + [self.ann1], ) def test_tickets_7448_7707(self): # Complex objects should be converted to strings before being used in # lookups. - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(created__in=[self.time1, self.time2]), - ['', ''] + [self.i1, self.i2], ) def test_ticket7235(self): @@ -756,9 +738,9 @@ class Queries1Tests(TestCase): # If a ValuesList or Values queryset is passed as an inner query, we # make sure it's only requesting a single value and use that as the # thing to select. - self.assertQuerysetEqual( + self.assertSequenceEqual( Tag.objects.filter(name__in=Tag.objects.filter(parent=self.t1).values('name')), - ['', ''] + [self.t2, self.t3], ) # Multi-valued values() and values_list() querysets should raise errors. @@ -773,9 +755,9 @@ class Queries1Tests(TestCase): Note.objects.values_list("note", flat=True).values("id").order_by("id"), [{'id': 1}, {'id': 2}, {'id': 3}] ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Annotation.objects.filter(notes__in=Note.objects.filter(note="n1").values_list('note').values('id')), - [''] + [self.ann1], ) def test_ticket10205(self): @@ -799,22 +781,22 @@ class Queries1Tests(TestCase): subq = Author.objects.filter(num__lt=3000) qs = Author.objects.filter(pk__in=subq) - self.assertQuerysetEqual(qs, ['', '']) + self.assertSequenceEqual(qs, [self.a1, self.a2]) # The subquery result cache should not be populated self.assertIsNone(subq._result_cache) subq = Author.objects.filter(num__lt=3000) qs = Author.objects.exclude(pk__in=subq) - self.assertQuerysetEqual(qs, ['', '']) + self.assertSequenceEqual(qs, [self.a3, self.a4]) # The subquery result cache should not be populated self.assertIsNone(subq._result_cache) subq = Author.objects.filter(num__lt=3000) - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.filter(Q(pk__in=subq) & Q(name='a1')), - [''] + [self.a1], ) # The subquery result cache should not be populated @@ -822,13 +804,13 @@ class Queries1Tests(TestCase): def test_ticket7076(self): # Excluding shouldn't eliminate NULL entries. - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.exclude(modified=self.time1).order_by('name'), - ['', '', ''] + [self.i4, self.i3, self.i2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Tag.objects.exclude(parent__name=self.t1.name), - ['', '', ''] + [self.t1, self.t4, self.t5], ) def test_ticket7181(self): @@ -838,36 +820,36 @@ class Queries1Tests(TestCase): self.assertEqual(len(Tag.objects.order_by('parent__name')), 5) # Empty querysets can be merged with others. - self.assertQuerysetEqual( + self.assertSequenceEqual( Note.objects.none() | Note.objects.all(), - ['', '', ''] + [self.n1, self.n2, self.n3], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Note.objects.all() | Note.objects.none(), - ['', '', ''] + [self.n1, self.n2, self.n3], ) - self.assertQuerysetEqual(Note.objects.none() & Note.objects.all(), []) - self.assertQuerysetEqual(Note.objects.all() & Note.objects.none(), []) + self.assertSequenceEqual(Note.objects.none() & Note.objects.all(), []) + self.assertSequenceEqual(Note.objects.all() & Note.objects.none(), []) def test_ticket8439(self): # Complex combinations of conjunctions, disjunctions and nullable # relations. - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.filter(Q(item__note__extrainfo=self.e2) | Q(report=self.r1, name='xyz')), - [''] + [self.a2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Author.objects.filter(Q(report=self.r1, name='xyz') | Q(item__note__extrainfo=self.e2)), - [''] + [self.a2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Annotation.objects.filter(Q(tag__parent=self.t1) | Q(notes__note='n1', name='a1')), - [''] + [self.ann1], ) xx = ExtraInfo.objects.create(info='xx', note=self.n3) - self.assertQuerysetEqual( + self.assertSequenceEqual( Note.objects.filter(Q(extrainfo__author=self.a1) | Q(extrainfo=xx)), - ['', ''] + [self.n1, self.n3], ) q = Note.objects.filter(Q(extrainfo__author=self.a1) | Q(extrainfo=xx)).query self.assertEqual( @@ -882,10 +864,9 @@ class Queries1Tests(TestCase): original_ordering = Tag._meta.ordering Tag._meta.ordering = None try: - self.assertQuerysetEqual( + self.assertCountEqual( Tag.objects.all(), - ['', '', '', '', ''], - ordered=False + [self.t1, self.t2, self.t3, self.t4, self.t5], ) finally: Tag._meta.ordering = original_ordering @@ -893,68 +874,59 @@ class Queries1Tests(TestCase): def test_exclude(self): self.assertQuerysetEqual( Item.objects.exclude(tags__name='t4'), - [repr(i) for i in Item.objects.filter(~Q(tags__name='t4'))]) + Item.objects.filter(~Q(tags__name='t4'))) self.assertQuerysetEqual( Item.objects.exclude(Q(tags__name='t4') | Q(tags__name='t3')), - [repr(i) for i in Item.objects.filter(~(Q(tags__name='t4') | Q(tags__name='t3')))]) + Item.objects.filter(~(Q(tags__name='t4') | Q(tags__name='t3')))) self.assertQuerysetEqual( Item.objects.exclude(Q(tags__name='t4') | ~Q(tags__name='t3')), - [repr(i) for i in Item.objects.filter(~(Q(tags__name='t4') | ~Q(tags__name='t3')))]) + Item.objects.filter(~(Q(tags__name='t4') | ~Q(tags__name='t3')))) def test_nested_exclude(self): self.assertQuerysetEqual( Item.objects.exclude(~Q(tags__name='t4')), - [repr(i) for i in Item.objects.filter(~~Q(tags__name='t4'))]) + Item.objects.filter(~~Q(tags__name='t4'))) def test_double_exclude(self): self.assertQuerysetEqual( Item.objects.filter(Q(tags__name='t4')), - [repr(i) for i in Item.objects.filter(~~Q(tags__name='t4'))]) + Item.objects.filter(~~Q(tags__name='t4'))) self.assertQuerysetEqual( Item.objects.filter(Q(tags__name='t4')), - [repr(i) for i in Item.objects.filter(~Q(~Q(tags__name='t4')))]) + Item.objects.filter(~Q(~Q(tags__name='t4')))) def test_exclude_in(self): self.assertQuerysetEqual( Item.objects.exclude(Q(tags__name__in=['t4', 't3'])), - [repr(i) for i in Item.objects.filter(~Q(tags__name__in=['t4', 't3']))]) + Item.objects.filter(~Q(tags__name__in=['t4', 't3']))) self.assertQuerysetEqual( Item.objects.filter(Q(tags__name__in=['t4', 't3'])), - [repr(i) for i in Item.objects.filter(~~Q(tags__name__in=['t4', 't3']))]) + Item.objects.filter(~~Q(tags__name__in=['t4', 't3']))) def test_ticket_10790_1(self): # Querying direct fields with isnull should trim the left outer join. # It also should not create INNER JOIN. q = Tag.objects.filter(parent__isnull=True) - self.assertQuerysetEqual(q, ['']) + self.assertSequenceEqual(q, [self.t1]) self.assertNotIn('JOIN', str(q.query)) q = Tag.objects.filter(parent__isnull=False) - self.assertQuerysetEqual( - q, - ['', '', '', ''], - ) + self.assertSequenceEqual(q, [self.t2, self.t3, self.t4, self.t5]) self.assertNotIn('JOIN', str(q.query)) q = Tag.objects.exclude(parent__isnull=True) - self.assertQuerysetEqual( - q, - ['', '', '', ''], - ) + self.assertSequenceEqual(q, [self.t2, self.t3, self.t4, self.t5]) self.assertNotIn('JOIN', str(q.query)) q = Tag.objects.exclude(parent__isnull=False) - self.assertQuerysetEqual(q, ['']) + self.assertSequenceEqual(q, [self.t1]) self.assertNotIn('JOIN', str(q.query)) q = Tag.objects.exclude(parent__parent__isnull=False) - self.assertQuerysetEqual( - q, - ['', '', ''], - ) + self.assertSequenceEqual(q, [self.t1, self.t2, self.t3]) self.assertEqual(str(q.query).count('LEFT OUTER JOIN'), 1) self.assertNotIn('INNER JOIN', str(q.query)) @@ -963,19 +935,13 @@ class Queries1Tests(TestCase): # while preserving the preceding inner joins. q = Tag.objects.filter(parent__parent__isnull=False) - self.assertQuerysetEqual( - q, - ['', ''], - ) + self.assertSequenceEqual(q, [self.t4, self.t5]) self.assertEqual(str(q.query).count('LEFT OUTER JOIN'), 0) self.assertEqual(str(q.query).count('INNER JOIN'), 1) # Querying without isnull should not convert anything to left outer join. q = Tag.objects.filter(parent__parent=self.t1) - self.assertQuerysetEqual( - q, - ['', ''], - ) + self.assertSequenceEqual(q, [self.t4, self.t5]) self.assertEqual(str(q.query).count('LEFT OUTER JOIN'), 0) self.assertEqual(str(q.query).count('INNER JOIN'), 1) @@ -985,56 +951,41 @@ class Queries1Tests(TestCase): self.assertEqual(str(q.query).count('LEFT OUTER JOIN'), 1) # join to dumbcategory ptr_id self.assertEqual(str(q.query).count('INNER JOIN'), 1) - self.assertQuerysetEqual(q, []) + self.assertSequenceEqual(q, []) # Querying across several tables should strip only the last join, while # preserving the preceding left outer joins. q = NamedCategory.objects.filter(tag__parent__isnull=True) self.assertEqual(str(q.query).count('INNER JOIN'), 1) self.assertEqual(str(q.query).count('LEFT OUTER JOIN'), 1) - self.assertQuerysetEqual(q, ['']) + self.assertSequenceEqual(q, [self.nc1]) def test_ticket_10790_4(self): # Querying across m2m field should not strip the m2m table from join. q = Author.objects.filter(item__tags__isnull=True) - self.assertQuerysetEqual( - q, - ['', ''], - ) + self.assertSequenceEqual(q, [self.a2, self.a3]) self.assertEqual(str(q.query).count('LEFT OUTER JOIN'), 2) self.assertNotIn('INNER JOIN', str(q.query)) q = Author.objects.filter(item__tags__parent__isnull=True) - self.assertQuerysetEqual( - q, - ['', '', '', ''], - ) + self.assertSequenceEqual(q, [self.a1, self.a2, self.a2, self.a3]) self.assertEqual(str(q.query).count('LEFT OUTER JOIN'), 3) self.assertNotIn('INNER JOIN', str(q.query)) def test_ticket_10790_5(self): # Querying with isnull=False across m2m field should not create outer joins q = Author.objects.filter(item__tags__isnull=False) - self.assertQuerysetEqual( - q, - ['', '', '', '', ''] - ) + self.assertSequenceEqual(q, [self.a1, self.a1, self.a2, self.a2, self.a4]) self.assertEqual(str(q.query).count('LEFT OUTER JOIN'), 0) self.assertEqual(str(q.query).count('INNER JOIN'), 2) q = Author.objects.filter(item__tags__parent__isnull=False) - self.assertQuerysetEqual( - q, - ['', '', ''] - ) + self.assertSequenceEqual(q, [self.a1, self.a2, self.a4]) self.assertEqual(str(q.query).count('LEFT OUTER JOIN'), 0) self.assertEqual(str(q.query).count('INNER JOIN'), 3) q = Author.objects.filter(item__tags__parent__parent__isnull=False) - self.assertQuerysetEqual( - q, - [''] - ) + self.assertSequenceEqual(q, [self.a4]) self.assertEqual(str(q.query).count('LEFT OUTER JOIN'), 0) self.assertEqual(str(q.query).count('INNER JOIN'), 4) @@ -1042,47 +993,34 @@ class Queries1Tests(TestCase): # Querying with isnull=True across m2m field should not create inner joins # and strip last outer join q = Author.objects.filter(item__tags__parent__parent__isnull=True) - self.assertQuerysetEqual( + self.assertSequenceEqual( q, - ['', '', '', '', - '', ''] + [self.a1, self.a1, self.a2, self.a2, self.a2, self.a3], ) self.assertEqual(str(q.query).count('LEFT OUTER JOIN'), 4) self.assertEqual(str(q.query).count('INNER JOIN'), 0) q = Author.objects.filter(item__tags__parent__isnull=True) - self.assertQuerysetEqual( - q, - ['', '', '', ''] - ) + self.assertSequenceEqual(q, [self.a1, self.a2, self.a2, self.a3]) self.assertEqual(str(q.query).count('LEFT OUTER JOIN'), 3) self.assertEqual(str(q.query).count('INNER JOIN'), 0) def test_ticket_10790_7(self): # Reverse querying with isnull should not strip the join q = Author.objects.filter(item__isnull=True) - self.assertQuerysetEqual( - q, - [''] - ) + self.assertSequenceEqual(q, [self.a3]) self.assertEqual(str(q.query).count('LEFT OUTER JOIN'), 1) self.assertEqual(str(q.query).count('INNER JOIN'), 0) q = Author.objects.filter(item__isnull=False) - self.assertQuerysetEqual( - q, - ['', '', '', ''] - ) + self.assertSequenceEqual(q, [self.a1, self.a2, self.a2, self.a4]) self.assertEqual(str(q.query).count('LEFT OUTER JOIN'), 0) self.assertEqual(str(q.query).count('INNER JOIN'), 1) def test_ticket_10790_8(self): # Querying with combined q-objects should also strip the left outer join q = Tag.objects.filter(Q(parent__isnull=True) | Q(parent=self.t1)) - self.assertQuerysetEqual( - q, - ['', '', ''] - ) + self.assertSequenceEqual(q, [self.t1, self.t2, self.t3]) self.assertEqual(str(q.query).count('LEFT OUTER JOIN'), 0) self.assertEqual(str(q.query).count('INNER JOIN'), 0) @@ -1092,32 +1030,23 @@ class Queries1Tests(TestCase): q2 = Tag.objects.filter(parent__isnull=False) q3 = q1 | q2 - self.assertQuerysetEqual( - q3, - ['', '', '', '', ''], - ) + self.assertSequenceEqual(q3, [self.t1, self.t2, self.t3, self.t4, self.t5]) self.assertEqual(str(q3.query).count('LEFT OUTER JOIN'), 0) self.assertEqual(str(q3.query).count('INNER JOIN'), 0) q3 = q1 & q2 - self.assertQuerysetEqual(q3, []) + self.assertSequenceEqual(q3, []) self.assertEqual(str(q3.query).count('LEFT OUTER JOIN'), 0) self.assertEqual(str(q3.query).count('INNER JOIN'), 0) q2 = Tag.objects.filter(parent=self.t1) q3 = q1 | q2 - self.assertQuerysetEqual( - q3, - ['', '', ''] - ) + self.assertSequenceEqual(q3, [self.t1, self.t2, self.t3]) self.assertEqual(str(q3.query).count('LEFT OUTER JOIN'), 0) self.assertEqual(str(q3.query).count('INNER JOIN'), 0) q3 = q2 | q1 - self.assertQuerysetEqual( - q3, - ['', '', ''] - ) + self.assertSequenceEqual(q3, [self.t1, self.t2, self.t3]) self.assertEqual(str(q3.query).count('LEFT OUTER JOIN'), 0) self.assertEqual(str(q3.query).count('INNER JOIN'), 0) @@ -1125,25 +1054,19 @@ class Queries1Tests(TestCase): q2 = Tag.objects.filter(parent__parent__isnull=True) q3 = q1 | q2 - self.assertQuerysetEqual( - q3, - ['', '', ''] - ) + self.assertSequenceEqual(q3, [self.t1, self.t2, self.t3]) self.assertEqual(str(q3.query).count('LEFT OUTER JOIN'), 1) self.assertEqual(str(q3.query).count('INNER JOIN'), 0) q3 = q2 | q1 - self.assertQuerysetEqual( - q3, - ['', '', ''] - ) + self.assertSequenceEqual(q3, [self.t1, self.t2, self.t3]) self.assertEqual(str(q3.query).count('LEFT OUTER JOIN'), 1) self.assertEqual(str(q3.query).count('INNER JOIN'), 0) def test_ticket19672(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Report.objects.filter(Q(creator__isnull=False) & ~Q(creator__extra__value=41)), - [''] + [self.r1], ) def test_ticket_20250(self): @@ -1152,10 +1075,7 @@ class Queries1Tests(TestCase): qs = qs.filter(~Q(extra__value=0)).order_by('name') self.assertIn('SELECT', str(qs.query)) - self.assertQuerysetEqual( - qs, - ['', '', '', ''] - ) + self.assertSequenceEqual(qs, [self.a1, self.a2, self.a3, self.a4]) def test_lookup_constraint_fielderror(self): msg = ( @@ -1219,99 +1139,91 @@ class Queries1Tests(TestCase): class Queries2Tests(TestCase): @classmethod def setUpTestData(cls): - Number.objects.create(num=4) - Number.objects.create(num=8) - Number.objects.create(num=12) + cls.num4 = Number.objects.create(num=4) + cls.num8 = Number.objects.create(num=8) + cls.num12 = Number.objects.create(num=12) def test_ticket4289(self): # A slight variation on the restricting the filtering choices by the # lookup constraints. - self.assertQuerysetEqual(Number.objects.filter(num__lt=4), []) - self.assertQuerysetEqual(Number.objects.filter(num__gt=8, num__lt=12), []) - self.assertQuerysetEqual( + self.assertSequenceEqual(Number.objects.filter(num__lt=4), []) + self.assertSequenceEqual(Number.objects.filter(num__gt=8, num__lt=12), []) + self.assertSequenceEqual( Number.objects.filter(num__gt=8, num__lt=13), - [''] + [self.num12], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Number.objects.filter(Q(num__lt=4) | Q(num__gt=8, num__lt=12)), [] ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Number.objects.filter(Q(num__gt=8, num__lt=12) | Q(num__lt=4)), [] ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Number.objects.filter(Q(num__gt=8) & Q(num__lt=12) | Q(num__lt=4)), [] ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Number.objects.filter(Q(num__gt=7) & Q(num__lt=12) | Q(num__lt=4)), - [''] + [self.num8], ) def test_ticket12239(self): # Custom lookups are registered to round float values correctly on gte # and lt IntegerField queries. - self.assertQuerysetEqual( + self.assertSequenceEqual( Number.objects.filter(num__gt=11.9), - [''] + [self.num12], ) - self.assertQuerysetEqual(Number.objects.filter(num__gt=12), []) - self.assertQuerysetEqual(Number.objects.filter(num__gt=12.0), []) - self.assertQuerysetEqual(Number.objects.filter(num__gt=12.1), []) - self.assertQuerysetEqual( + self.assertSequenceEqual(Number.objects.filter(num__gt=12), []) + self.assertSequenceEqual(Number.objects.filter(num__gt=12.0), []) + self.assertSequenceEqual(Number.objects.filter(num__gt=12.1), []) + self.assertCountEqual( Number.objects.filter(num__lt=12), - ['', ''], - ordered=False + [self.num4, self.num8], ) - self.assertQuerysetEqual( + self.assertCountEqual( Number.objects.filter(num__lt=12.0), - ['', ''], - ordered=False + [self.num4, self.num8], ) - self.assertQuerysetEqual( + self.assertCountEqual( Number.objects.filter(num__lt=12.1), - ['', '', ''], - ordered=False + [self.num4, self.num8, self.num12], ) - self.assertQuerysetEqual( + self.assertCountEqual( Number.objects.filter(num__gte=11.9), - [''] + [self.num12], ) - self.assertQuerysetEqual( + self.assertCountEqual( Number.objects.filter(num__gte=12), - [''] + [self.num12], ) - self.assertQuerysetEqual( + self.assertCountEqual( Number.objects.filter(num__gte=12.0), - [''] + [self.num12], ) - self.assertQuerysetEqual(Number.objects.filter(num__gte=12.1), []) - self.assertQuerysetEqual(Number.objects.filter(num__gte=12.9), []) - self.assertQuerysetEqual( + self.assertSequenceEqual(Number.objects.filter(num__gte=12.1), []) + self.assertSequenceEqual(Number.objects.filter(num__gte=12.9), []) + self.assertCountEqual( Number.objects.filter(num__lte=11.9), - ['', ''], - ordered=False + [self.num4, self.num8], ) - self.assertQuerysetEqual( + self.assertCountEqual( Number.objects.filter(num__lte=12), - ['', '', ''], - ordered=False + [self.num4, self.num8, self.num12], ) - self.assertQuerysetEqual( + self.assertCountEqual( Number.objects.filter(num__lte=12.0), - ['', '', ''], - ordered=False + [self.num4, self.num8, self.num12], ) - self.assertQuerysetEqual( + self.assertCountEqual( Number.objects.filter(num__lte=12.1), - ['', '', ''], - ordered=False + [self.num4, self.num8, self.num12], ) - self.assertQuerysetEqual( + self.assertCountEqual( Number.objects.filter(num__lte=12.9), - ['', '', ''], - ordered=False + [self.num4, self.num8, self.num12], ) def test_ticket7759(self): @@ -1363,8 +1275,8 @@ class Queries4Tests(TestCase): cls.r2 = Report.objects.create(name='r2', creator=cls.a3) cls.r3 = Report.objects.create(name='r3') - Item.objects.create(name='i1', created=datetime.datetime.now(), note=n1, creator=cls.a1) - Item.objects.create(name='i2', created=datetime.datetime.now(), note=n1, creator=cls.a3) + cls.i1 = Item.objects.create(name='i1', created=datetime.datetime.now(), note=n1, creator=cls.a1) + cls.i2 = Item.objects.create(name='i2', created=datetime.datetime.now(), note=n1, creator=cls.a3) def test_ticket24525(self): tag = Tag.objects.create() @@ -1390,12 +1302,12 @@ class Queries4Tests(TestCase): # and results will be incorrect. q1 = Report.objects.filter(Q(creator__isnull=True) | Q(creator__extra__info='e1')) q2 = Report.objects.filter(Q(creator__isnull=True)) | Report.objects.filter(Q(creator__extra__info='e1')) - self.assertQuerysetEqual(q1, ["", ""], ordered=False) + self.assertCountEqual(q1, [self.r1, self.r3]) self.assertEqual(str(q1.query), str(q2.query)) q1 = Report.objects.filter(Q(creator__extra__info='e1') | Q(creator__isnull=True)) q2 = Report.objects.filter(Q(creator__extra__info='e1')) | Report.objects.filter(Q(creator__isnull=True)) - self.assertQuerysetEqual(q1, ["", ""], ordered=False) + self.assertCountEqual(q1, [self.r1, self.r3]) self.assertEqual(str(q1.query), str(q2.query)) q1 = Item.objects.filter(Q(creator=self.a1) | Q(creator__report__name='r1')).order_by() @@ -1404,7 +1316,7 @@ class Queries4Tests(TestCase): .filter(Q(creator=self.a1)).order_by() | Item.objects.filter(Q(creator__report__name='r1')) .order_by() ) - self.assertQuerysetEqual(q1, [""]) + self.assertCountEqual(q1, [self.i1]) self.assertEqual(str(q1.query), str(q2.query)) q1 = Item.objects.filter(Q(creator__report__name='e1') | Q(creator=self.a1)).order_by() @@ -1412,7 +1324,7 @@ class Queries4Tests(TestCase): Item.objects.filter(Q(creator__report__name='e1')).order_by() | Item.objects.filter(Q(creator=self.a1)).order_by() ) - self.assertQuerysetEqual(q1, [""]) + self.assertCountEqual(q1, [self.i1]) self.assertEqual(str(q1.query), str(q2.query)) def test_combine_join_reuse(self): @@ -1459,9 +1371,9 @@ class Queries4Tests(TestCase): # Similarly for select_related(), joins beyond an initial nullable join # must use outer joins so that all results are included. - self.assertQuerysetEqual( + self.assertSequenceEqual( Report.objects.select_related("creator", "creator__extra").order_by("name"), - ['', '', ''] + [self.r1, self.r2, self.r3] ) # When there are multiple paths to a table from another table, we have @@ -1631,33 +1543,33 @@ class Queries5Tests(TestCase): def setUpTestData(cls): # Ordering by 'rank' gives us rank2, rank1, rank3. Ordering by the # Meta.ordering will be rank3, rank2, rank1. - n1 = Note.objects.create(note='n1', misc='foo', id=1) - n2 = Note.objects.create(note='n2', misc='bar', id=2) - e1 = ExtraInfo.objects.create(info='e1', note=n1) - e2 = ExtraInfo.objects.create(info='e2', note=n2) + cls.n1 = Note.objects.create(note='n1', misc='foo', id=1) + cls.n2 = Note.objects.create(note='n2', misc='bar', id=2) + e1 = ExtraInfo.objects.create(info='e1', note=cls.n1) + e2 = ExtraInfo.objects.create(info='e2', note=cls.n2) a1 = Author.objects.create(name='a1', num=1001, extra=e1) a2 = Author.objects.create(name='a2', num=2002, extra=e1) a3 = Author.objects.create(name='a3', num=3003, extra=e2) - cls.rank1 = Ranking.objects.create(rank=2, author=a2) - Ranking.objects.create(rank=1, author=a3) - Ranking.objects.create(rank=3, author=a1) + cls.rank2 = Ranking.objects.create(rank=2, author=a2) + cls.rank1 = Ranking.objects.create(rank=1, author=a3) + cls.rank3 = Ranking.objects.create(rank=3, author=a1) def test_ordering(self): # Cross model ordering is possible in Meta, too. - self.assertQuerysetEqual( + self.assertSequenceEqual( Ranking.objects.all(), - ['', '', ''] + [self.rank3, self.rank2, self.rank1], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Ranking.objects.all().order_by('rank'), - ['', '', ''] + [self.rank1, self.rank2, self.rank3], ) # Ordering of extra() pieces is possible, too and you can mix extra # fields and model fields in the ordering. - self.assertQuerysetEqual( + self.assertSequenceEqual( Ranking.objects.extra(tables=['django_site'], order_by=['-django_site.id', 'rank']), - ['', '', ''] + [self.rank1, self.rank2, self.rank3], ) sql = 'case when %s > 2 then 1 else 0 end' % connection.ops.quote_name('rank') @@ -1666,9 +1578,9 @@ class Queries5Tests(TestCase): [o.good for o in qs.extra(order_by=('-good',))], [True, False, False] ) - self.assertQuerysetEqual( + self.assertSequenceEqual( qs.extra(order_by=('-good', 'id')), - ['', '', ''] + [self.rank3, self.rank2, self.rank1], ) # Despite having some extra aliases in the query, we can still omit @@ -1707,9 +1619,9 @@ class Queries5Tests(TestCase): ranking_start = Ranking.objects.get(author__name='a1') # Make sure that the IDs from different tables don't happen to match. - self.assertQuerysetEqual( + self.assertSequenceEqual( Ranking.objects.filter(author__name='a1'), - [''] + [self.rank3], ) self.assertEqual( Ranking.objects.filter(author__name='a1').update(rank=4636), @@ -1722,28 +1634,28 @@ class Queries5Tests(TestCase): self.assertEqual(r.rank, 4636) r.rank = 3 r.save() - self.assertQuerysetEqual( + self.assertSequenceEqual( Ranking.objects.all(), - ['', '', ''] + [self.rank3, self.rank2, self.rank1], ) def test_ticket5261(self): # Test different empty excludes. - self.assertQuerysetEqual( + self.assertSequenceEqual( Note.objects.exclude(Q()), - ['', ''] + [self.n1, self.n2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Note.objects.filter(~Q()), - ['', ''] + [self.n1, self.n2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Note.objects.filter(~Q() | ~Q()), - ['', ''] + [self.n1, self.n2], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Note.objects.exclude(~Q() & ~Q()), - ['', ''] + [self.n1, self.n2], ) def test_extra_select_literal_percent_s(self): @@ -1796,11 +1708,8 @@ class NullableRelOrderingTests(TestCase): def test_ticket10028(self): # Ordering by model related to nullable relations(!) should use outer # joins, so that all results are included. - Plaything.objects.create(name="p1") - self.assertQuerysetEqual( - Plaything.objects.all(), - [''] - ) + p1 = Plaything.objects.create(name="p1") + self.assertSequenceEqual(Plaything.objects.all(), [p1]) def test_join_already_in_query(self): # Ordering by model related to nullable relations should not change @@ -1808,7 +1717,7 @@ class NullableRelOrderingTests(TestCase): Plaything.objects.create(name="p1") s = SingleObject.objects.create(name='s') r = RelatedObject.objects.create(single=s, f=1) - Plaything.objects.create(name="p2", others=r) + p2 = Plaything.objects.create(name="p2", others=r) qs = Plaything.objects.all().filter(others__isnull=False).order_by('pk') self.assertNotIn('JOIN', str(qs.query)) qs = Plaything.objects.all().filter(others__f__isnull=False).order_by('pk') @@ -1820,39 +1729,36 @@ class NullableRelOrderingTests(TestCase): # in the query. self.assertEqual(str(qs.query).count('LEFT'), 1) self.assertEqual(str(qs.query).count('INNER'), 1) - self.assertQuerysetEqual( - qs, - [''] - ) + self.assertSequenceEqual(qs, [p2]) class DisjunctiveFilterTests(TestCase): @classmethod def setUpTestData(cls): cls.n1 = Note.objects.create(note='n1', misc='foo', id=1) - ExtraInfo.objects.create(info='e1', note=cls.n1) + cls.e1 = ExtraInfo.objects.create(info='e1', note=cls.n1) def test_ticket7872(self): # Another variation on the disjunctive filtering theme. # For the purposes of this regression test, it's important that there is no # Join object related to the LeafA we create. - LeafA.objects.create(data='first') - self.assertQuerysetEqual(LeafA.objects.all(), ['']) - self.assertQuerysetEqual( + l1 = LeafA.objects.create(data='first') + self.assertSequenceEqual(LeafA.objects.all(), [l1]) + self.assertSequenceEqual( LeafA.objects.filter(Q(data='first') | Q(join__b__data='second')), - [''] + [l1], ) def test_ticket8283(self): # Checking that applying filters after a disjunction works correctly. - self.assertQuerysetEqual( + self.assertSequenceEqual( (ExtraInfo.objects.filter(note=self.n1) | ExtraInfo.objects.filter(info='e2')).filter(note=self.n1), - [''] + [self.e1], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( (ExtraInfo.objects.filter(info='e2') | ExtraInfo.objects.filter(note=self.n1)).filter(note=self.n1), - [''] + [self.e1], ) @@ -1866,9 +1772,9 @@ class Queries6Tests(TestCase): cls.t4 = Tag.objects.create(name='t4', parent=cls.t3) cls.t5 = Tag.objects.create(name='t5', parent=cls.t3) n1 = Note.objects.create(note='n1', misc='foo', id=1) - ann1 = Annotation.objects.create(name='a1', tag=cls.t1) - ann1.notes.add(n1) - Annotation.objects.create(name='a2', tag=cls.t4) + cls.ann1 = Annotation.objects.create(name='a1', tag=cls.t1) + cls.ann1.notes.add(n1) + cls.ann2 = Annotation.objects.create(name='a2', tag=cls.t4) def test_parallel_iterators(self): # Parallel iterators work. @@ -1899,40 +1805,40 @@ class Queries6Tests(TestCase): # queries that crossed multi-valued relations (#8921, #9188 and some # preemptively discovered cases). - self.assertQuerysetEqual( + self.assertSequenceEqual( PointerA.objects.filter(connection__pointerb__id=1), [] ) - self.assertQuerysetEqual( + self.assertSequenceEqual( PointerA.objects.exclude(connection__pointerb__id=1), [] ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Tag.objects.exclude(children=None), - ['', ''] + [self.t1, self.t3], ) # This example is tricky because the parent could be NULL, so only checking # parents with annotations omits some results (tag t1, in this case). - self.assertQuerysetEqual( + self.assertSequenceEqual( Tag.objects.exclude(parent__annotation__name="a1"), - ['', '', ''] + [self.t1, self.t4, self.t5], ) # The annotation->tag link is single values and tag->children links is # multi-valued. So we have to split the exclude filter in the middle # and then optimize the inner query without losing results. - self.assertQuerysetEqual( + self.assertSequenceEqual( Annotation.objects.exclude(tag__children__name="t2"), - [''] + [self.ann2], ) # Nested queries are possible (although should be used with care, since # they have performance problems on backends like MySQL. - self.assertQuerysetEqual( + self.assertSequenceEqual( Annotation.objects.filter(notes__in=Note.objects.filter(note="n1")), - [''] + [self.ann1], ) def test_ticket3739(self): @@ -2000,23 +1906,23 @@ class ComparisonTests(TestCase): def test_ticket8597(self): # Regression tests for case-insensitive comparisons - Item.objects.create(name="a_b", created=datetime.datetime.now(), creator=self.a2, note=self.n1) - Item.objects.create(name="x%y", created=datetime.datetime.now(), creator=self.a2, note=self.n1) - self.assertQuerysetEqual( + item_ab = Item.objects.create(name="a_b", created=datetime.datetime.now(), creator=self.a2, note=self.n1) + item_xy = Item.objects.create(name="x%y", created=datetime.datetime.now(), creator=self.a2, note=self.n1) + self.assertSequenceEqual( Item.objects.filter(name__iexact="A_b"), - [''] + [item_ab], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(name__iexact="x%Y"), - [''] + [item_xy], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(name__istartswith="A_b"), - [''] + [item_ab], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.filter(name__iendswith="A_b"), - [''] + [item_ab], ) @@ -2411,27 +2317,28 @@ class QuerySetSupportsPythonIdioms(TestCase): @classmethod def setUpTestData(cls): some_date = datetime.datetime(2014, 5, 16, 12, 1) - for i in range(1, 8): - Article.objects.create( - name="Article {}".format(i), created=some_date) + cls.articles = [ + Article.objects.create(name=f'Article {i}', created=some_date) + for i in range(1, 8) + ] def get_ordered_articles(self): return Article.objects.all().order_by('name') def test_can_get_items_using_index_and_slice_notation(self): self.assertEqual(self.get_ordered_articles()[0].name, 'Article 1') - self.assertQuerysetEqual( + self.assertSequenceEqual( self.get_ordered_articles()[1:3], - ["", ""] + [self.articles[1], self.articles[2]], ) def test_slicing_with_steps_can_be_used(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( self.get_ordered_articles()[::2], [ - "", - "", - "", - "" + self.articles[0], + self.articles[2], + self.articles[4], + self.articles[6], ] ) @@ -2444,28 +2351,28 @@ class QuerySetSupportsPythonIdioms(TestCase): self.get_ordered_articles()[0:5:3] def test_slicing_can_slice_again_after_slicing(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( self.get_ordered_articles()[0:5][0:2], - ["", ""] + [self.articles[0], self.articles[1]], ) - self.assertQuerysetEqual(self.get_ordered_articles()[0:5][4:], [""]) - self.assertQuerysetEqual(self.get_ordered_articles()[0:5][5:], []) + self.assertSequenceEqual(self.get_ordered_articles()[0:5][4:], [self.articles[4]]) + self.assertSequenceEqual(self.get_ordered_articles()[0:5][5:], []) # Some more tests! - self.assertQuerysetEqual( + self.assertSequenceEqual( self.get_ordered_articles()[2:][0:2], - ["", ""] + [self.articles[2], self.articles[3]], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( self.get_ordered_articles()[2:][:2], - ["", ""] + [self.articles[2], self.articles[3]], ) - self.assertQuerysetEqual(self.get_ordered_articles()[2:][2:3], [""]) + self.assertSequenceEqual(self.get_ordered_articles()[2:][2:3], [self.articles[4]]) # Using an offset without a limit is also possible. - self.assertQuerysetEqual( + self.assertSequenceEqual( self.get_ordered_articles()[5:], - ["", ""] + [self.articles[5], self.articles[6]], ) def test_slicing_cannot_filter_queryset_once_sliced(self): @@ -2501,11 +2408,11 @@ class QuerySetSupportsPythonIdioms(TestCase): def test_can_combine_queries_using_and_and_or_operators(self): s1 = Article.objects.filter(name__exact='Article 1') s2 = Article.objects.filter(name__exact='Article 2') - self.assertQuerysetEqual( + self.assertSequenceEqual( (s1 | s2).order_by('name'), - ["", ""] + [self.articles[0], self.articles[1]], ) - self.assertQuerysetEqual(s1 & s2, []) + self.assertSequenceEqual(s1 & s2, []) class WeirdQuerysetSlicingTests(TestCase): @@ -2550,15 +2457,15 @@ class WeirdQuerysetSlicingTests(TestCase): class EscapingTests(TestCase): def test_ticket_7302(self): # Reserved names are appropriately escaped - ReservedName.objects.create(name='a', order=42) - ReservedName.objects.create(name='b', order=37) - self.assertQuerysetEqual( + r_a = ReservedName.objects.create(name='a', order=42) + r_b = ReservedName.objects.create(name='b', order=37) + self.assertSequenceEqual( ReservedName.objects.all().order_by('order'), - ['', ''] + [r_b, r_a], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( ReservedName.objects.extra(select={'stuff': 'name'}, order_by=('order', 'stuff')), - ['', ''] + [r_b, r_a], ) @@ -2661,15 +2568,15 @@ class IsNullTests(TestCase): def test_to_field(self): apple = Food.objects.create(name="apple") - Eaten.objects.create(food=apple, meal="lunch") - Eaten.objects.create(meal="lunch") - self.assertQuerysetEqual( + e1 = Eaten.objects.create(food=apple, meal="lunch") + e2 = Eaten.objects.create(meal="lunch") + self.assertSequenceEqual( Eaten.objects.filter(food__isnull=False), - [''] + [e1], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Eaten.objects.filter(food__isnull=True), - [''] + [e2], ) @@ -2805,25 +2712,28 @@ class ExcludeTests(TestCase): @classmethod def setUpTestData(cls): f1 = Food.objects.create(name='apples') - Food.objects.create(name='oranges') + cls.f2 = Food.objects.create(name='oranges') Eaten.objects.create(food=f1, meal='dinner') cls.j1 = Job.objects.create(name='Manager') cls.r1 = Responsibility.objects.create(description='Playing golf') - j2 = Job.objects.create(name='Programmer') - r2 = Responsibility.objects.create(description='Programming') + cls.j2 = Job.objects.create(name='Programmer') + cls.r2 = Responsibility.objects.create(description='Programming') JobResponsibilities.objects.create(job=cls.j1, responsibility=cls.r1) - JobResponsibilities.objects.create(job=j2, responsibility=r2) + JobResponsibilities.objects.create(job=cls.j2, responsibility=cls.r2) def test_to_field(self): - self.assertQuerysetEqual( + self.assertSequenceEqual( Food.objects.exclude(eaten__meal='dinner'), - ['']) - self.assertQuerysetEqual( + [self.f2], + ) + self.assertSequenceEqual( Job.objects.exclude(responsibilities__description='Playing golf'), - ['']) - self.assertQuerysetEqual( + [self.j2], + ) + self.assertSequenceEqual( Responsibility.objects.exclude(jobs__name='Manager'), - ['']) + [self.r2], + ) def test_ticket14511(self): alex = Person.objects.get_or_create(name='Alex')[0] @@ -2927,33 +2837,37 @@ class ExcludeTest17600(TestCase): """ This should exclude Orders which have some items with status 1 """ - self.assertQuerysetEqual( + self.assertSequenceEqual( Order.objects.exclude(items__status=1), - ['']) + [self.o3], + ) def test_exclude_plain_distinct(self): """ This should exclude Orders which have some items with status 1 """ - self.assertQuerysetEqual( + self.assertSequenceEqual( Order.objects.exclude(items__status=1).distinct(), - ['']) + [self.o3], + ) def test_exclude_with_q_object_distinct(self): """ This should exclude Orders which have some items with status 1 """ - self.assertQuerysetEqual( + self.assertSequenceEqual( Order.objects.exclude(Q(items__status=1)).distinct(), - ['']) + [self.o3], + ) def test_exclude_with_q_object_no_distinct(self): """ This should exclude Orders which have some items with status 1 """ - self.assertQuerysetEqual( + self.assertSequenceEqual( Order.objects.exclude(Q(items__status=1)), - ['']) + [self.o3], + ) def test_exclude_with_q_is_equal_to_plain_exclude(self): """ @@ -2982,7 +2896,8 @@ class ExcludeTest17600(TestCase): """ self.assertQuerysetEqual( Order.objects.exclude(~Q(items__status=1)).distinct(), - ['']) + [self.o1], + ) class Exclude15786(TestCase): @@ -3528,20 +3443,22 @@ class DisjunctionPromotionTests(TestCase): class ManyToManyExcludeTest(TestCase): def test_exclude_many_to_many(self): - Identifier.objects.create(name='extra') - program = Program.objects.create(identifier=Identifier.objects.create(name='program')) - channel = Channel.objects.create(identifier=Identifier.objects.create(name='channel')) + i_extra = Identifier.objects.create(name='extra') + i_program = Identifier.objects.create(name='program') + program = Program.objects.create(identifier=i_program) + i_channel = Identifier.objects.create(name='channel') + channel = Channel.objects.create(identifier=i_channel) channel.programs.add(program) # channel contains 'program1', so all Identifiers except that one # should be returned - self.assertQuerysetEqual( + self.assertSequenceEqual( Identifier.objects.exclude(program__channel=channel).order_by('name'), - ['', ''] + [i_channel, i_extra], ) - self.assertQuerysetEqual( + self.assertSequenceEqual( Identifier.objects.exclude(program__channel=None).order_by('name'), - [''] + [i_program], ) def test_ticket_12823(self): @@ -3687,9 +3604,9 @@ class RelatedLookupTypeTests(TestCase): cls.coa = ChildObjectA.objects.create(name="coa") cls.wrong_type = Order.objects.create(id=cls.oa.pk) cls.ob = ObjectB.objects.create(name="ob", objecta=cls.oa, num=1) - ProxyObjectB.objects.create(name="pob", objecta=cls.oa, num=2) + cls.pob1 = ProxyObjectB.objects.create(name="pob", objecta=cls.oa, num=2) cls.pob = ProxyObjectB.objects.all() - ObjectC.objects.create(childobjecta=cls.coa) + cls.c = ObjectC.objects.create(childobjecta=cls.coa) def test_wrong_type_lookup(self): """ @@ -3735,24 +3652,24 @@ class RelatedLookupTypeTests(TestCase): When passing proxy model objects, child objects, or parent objects, lookups work fine. """ - out_a = [''] - out_b = ['', ''] - out_c = [''] + out_a = [self.oa] + out_b = [self.ob, self.pob1] + out_c = [self.c] # proxy model objects - self.assertQuerysetEqual(ObjectB.objects.filter(objecta=self.poa).order_by('name'), out_b) - self.assertQuerysetEqual(ObjectA.objects.filter(objectb__in=self.pob).order_by('pk'), out_a * 2) + self.assertSequenceEqual(ObjectB.objects.filter(objecta=self.poa).order_by('name'), out_b) + self.assertSequenceEqual(ObjectA.objects.filter(objectb__in=self.pob).order_by('pk'), out_a * 2) # child objects - self.assertQuerysetEqual(ObjectB.objects.filter(objecta__in=[self.coa]), []) - self.assertQuerysetEqual(ObjectB.objects.filter(objecta__in=[self.poa, self.coa]).order_by('name'), out_b) - self.assertQuerysetEqual( + self.assertSequenceEqual(ObjectB.objects.filter(objecta__in=[self.coa]), []) + self.assertSequenceEqual(ObjectB.objects.filter(objecta__in=[self.poa, self.coa]).order_by('name'), out_b) + self.assertSequenceEqual( ObjectB.objects.filter(objecta__in=iter([self.poa, self.coa])).order_by('name'), out_b ) # parent objects - self.assertQuerysetEqual(ObjectC.objects.exclude(childobjecta=self.oa), out_c) + self.assertSequenceEqual(ObjectC.objects.exclude(childobjecta=self.oa), out_c) # QuerySet related object type checking shouldn't issue queries # (the querysets aren't evaluated here, hence zero queries) (#23266). @@ -3770,9 +3687,9 @@ class RelatedLookupTypeTests(TestCase): pob = ObjectB.objects.get(name='pob') pob.num = pob.objecta.pk pob.save() - self.assertQuerysetEqual(ObjectB.objects.filter( + self.assertSequenceEqual(ObjectB.objects.filter( objecta__in=ObjectB.objects.all().values_list('num') - ).order_by('pk'), ['', '']) + ).order_by('pk'), [ob, pob]) class Ticket14056Tests(TestCase): diff --git a/tests/select_related_regress/tests.py b/tests/select_related_regress/tests.py index 753114a6d2f..47e5e4f3c9d 100644 --- a/tests/select_related_regress/tests.py +++ b/tests/select_related_regress/tests.py @@ -100,12 +100,12 @@ class SelectRelatedRegressTests(TestCase): def test_multi_table_inheritance(self): """ Exercising select_related() with multi-table model inheritance. """ c1 = Child.objects.create(name="child1", value=42) - Item.objects.create(name="item1", child=c1) - Item.objects.create(name="item2") + i1 = Item.objects.create(name="item1", child=c1) + i2 = Item.objects.create(name="item2") - self.assertQuerysetEqual( + self.assertSequenceEqual( Item.objects.select_related("child").order_by("name"), - ["", ""] + [i1, i2], ) def test_regression_12851(self): diff --git a/tests/test_utils/tests.py b/tests/test_utils/tests.py index 51e3c0548a0..9255315e98d 100644 --- a/tests/test_utils/tests.py +++ b/tests/test_utils/tests.py @@ -16,8 +16,8 @@ from django.forms import EmailField, IntegerField from django.http import HttpResponse from django.template.loader import render_to_string from django.test import ( - SimpleTestCase, TestCase, TransactionTestCase, skipIfDBFeature, - skipUnlessDBFeature, + SimpleTestCase, TestCase, TransactionTestCase, ignore_warnings, + skipIfDBFeature, skipUnlessDBFeature, ) from django.test.html import HTMLParseError, parse_html from django.test.utils import ( @@ -25,6 +25,7 @@ from django.test.utils import ( override_settings, setup_test_environment, ) from django.urls import NoReverseMatch, path, reverse, reverse_lazy +from django.utils.deprecation import RemovedInDjango41Warning from .models import Car, Person, PossessedCar from .views import empty_response @@ -243,19 +244,34 @@ class AssertQuerysetEqualTests(TestCase): cls.p1 = Person.objects.create(name='p1') cls.p2 = Person.objects.create(name='p2') + def test_empty(self): + self.assertQuerysetEqual(Person.objects.filter(name='p3'), []) + def test_ordered(self): self.assertQuerysetEqual( Person.objects.all().order_by('name'), - [repr(self.p1), repr(self.p2)] + [self.p1, self.p2], ) def test_unordered(self): self.assertQuerysetEqual( Person.objects.all().order_by('name'), - [repr(self.p2), repr(self.p1)], + [self.p2, self.p1], ordered=False ) + def test_queryset(self): + self.assertQuerysetEqual( + Person.objects.all().order_by('name'), + Person.objects.all().order_by('name'), + ) + + def test_flat_values_list(self): + self.assertQuerysetEqual( + Person.objects.all().order_by('name').values_list('name', flat=True), + ['p1', 'p2'], + ) + def test_transform(self): self.assertQuerysetEqual( Person.objects.all().order_by('name'), @@ -263,6 +279,13 @@ class AssertQuerysetEqualTests(TestCase): transform=lambda x: x.pk ) + def test_repr_transform(self): + self.assertQuerysetEqual( + Person.objects.all().order_by('name'), + [repr(self.p1), repr(self.p2)], + transform=repr, + ) + def test_undefined_order(self): # Using an unordered queryset with more than one ordered value # is an error. @@ -270,13 +293,10 @@ class AssertQuerysetEqualTests(TestCase): with self.assertRaisesMessage(ValueError, msg): self.assertQuerysetEqual( Person.objects.all(), - [repr(self.p1), repr(self.p2)] + [self.p1, self.p2], ) # No error for one value. - self.assertQuerysetEqual( - Person.objects.filter(name='p1'), - [repr(self.p1)] - ) + self.assertQuerysetEqual(Person.objects.filter(name='p1'), [self.p1]) def test_repeated_values(self): """ @@ -296,16 +316,42 @@ class AssertQuerysetEqualTests(TestCase): with self.assertRaises(AssertionError): self.assertQuerysetEqual( self.p1.cars.all(), - [repr(batmobile), repr(k2000)], + [batmobile, k2000], ordered=False ) self.assertQuerysetEqual( self.p1.cars.all(), - [repr(batmobile)] * 2 + [repr(k2000)] * 4, + [batmobile] * 2 + [k2000] * 4, ordered=False ) +class AssertQuerysetEqualDeprecationTests(TestCase): + @classmethod + def setUpTestData(cls): + cls.p1 = Person.objects.create(name='p1') + cls.p2 = Person.objects.create(name='p2') + + @ignore_warnings(category=RemovedInDjango41Warning) + def test_str_values(self): + self.assertQuerysetEqual( + Person.objects.all().order_by('name'), + [repr(self.p1), repr(self.p2)], + ) + + def test_str_values_warning(self): + msg = ( + "In Django 4.1, repr() will not be called automatically on a " + "queryset when compared to string values. Set an explicit " + "'transform' to silence this warning." + ) + with self.assertRaisesMessage(RemovedInDjango41Warning, msg): + self.assertQuerysetEqual( + Person.objects.all().order_by('name'), + [repr(self.p1), repr(self.p2)], + ) + + @override_settings(ROOT_URLCONF='test_utils.urls') class CaptureQueriesContextManagerTests(TestCase): diff --git a/tests/transactions/tests.py b/tests/transactions/tests.py index 2ac2f8cc844..a4d64222beb 100644 --- a/tests/transactions/tests.py +++ b/tests/transactions/tests.py @@ -32,9 +32,9 @@ class AtomicTests(TransactionTestCase): def test_decorator_syntax_commit(self): @transaction.atomic def make_reporter(): - Reporter.objects.create(first_name="Tintin") - make_reporter() - self.assertQuerysetEqual(Reporter.objects.all(), ['']) + return Reporter.objects.create(first_name="Tintin") + reporter = make_reporter() + self.assertSequenceEqual(Reporter.objects.all(), [reporter]) def test_decorator_syntax_rollback(self): @transaction.atomic @@ -43,14 +43,14 @@ class AtomicTests(TransactionTestCase): raise Exception("Oops, that's his last name") with self.assertRaisesMessage(Exception, "Oops"): make_reporter() - self.assertQuerysetEqual(Reporter.objects.all(), []) + self.assertSequenceEqual(Reporter.objects.all(), []) def test_alternate_decorator_syntax_commit(self): @transaction.atomic() def make_reporter(): - Reporter.objects.create(first_name="Tintin") - make_reporter() - self.assertQuerysetEqual(Reporter.objects.all(), ['']) + return Reporter.objects.create(first_name="Tintin") + reporter = make_reporter() + self.assertSequenceEqual(Reporter.objects.all(), [reporter]) def test_alternate_decorator_syntax_rollback(self): @transaction.atomic() @@ -59,38 +59,35 @@ class AtomicTests(TransactionTestCase): raise Exception("Oops, that's his last name") with self.assertRaisesMessage(Exception, "Oops"): make_reporter() - self.assertQuerysetEqual(Reporter.objects.all(), []) + self.assertSequenceEqual(Reporter.objects.all(), []) def test_commit(self): with transaction.atomic(): - Reporter.objects.create(first_name="Tintin") - self.assertQuerysetEqual(Reporter.objects.all(), ['']) + reporter = Reporter.objects.create(first_name="Tintin") + self.assertSequenceEqual(Reporter.objects.all(), [reporter]) def test_rollback(self): with self.assertRaisesMessage(Exception, "Oops"): with transaction.atomic(): Reporter.objects.create(first_name="Haddock") raise Exception("Oops, that's his last name") - self.assertQuerysetEqual(Reporter.objects.all(), []) + self.assertSequenceEqual(Reporter.objects.all(), []) def test_nested_commit_commit(self): with transaction.atomic(): - Reporter.objects.create(first_name="Tintin") + reporter1 = Reporter.objects.create(first_name="Tintin") with transaction.atomic(): - Reporter.objects.create(first_name="Archibald", last_name="Haddock") - self.assertQuerysetEqual( - Reporter.objects.all(), - ['', ''] - ) + reporter2 = Reporter.objects.create(first_name="Archibald", last_name="Haddock") + self.assertSequenceEqual(Reporter.objects.all(), [reporter2, reporter1]) def test_nested_commit_rollback(self): with transaction.atomic(): - Reporter.objects.create(first_name="Tintin") + reporter = Reporter.objects.create(first_name="Tintin") with self.assertRaisesMessage(Exception, "Oops"): with transaction.atomic(): Reporter.objects.create(first_name="Haddock") raise Exception("Oops, that's his last name") - self.assertQuerysetEqual(Reporter.objects.all(), ['']) + self.assertSequenceEqual(Reporter.objects.all(), [reporter]) def test_nested_rollback_commit(self): with self.assertRaisesMessage(Exception, "Oops"): @@ -99,7 +96,7 @@ class AtomicTests(TransactionTestCase): with transaction.atomic(): Reporter.objects.create(last_name="Haddock") raise Exception("Oops, that's his first name") - self.assertQuerysetEqual(Reporter.objects.all(), []) + self.assertSequenceEqual(Reporter.objects.all(), []) def test_nested_rollback_rollback(self): with self.assertRaisesMessage(Exception, "Oops"): @@ -110,17 +107,14 @@ class AtomicTests(TransactionTestCase): Reporter.objects.create(first_name="Haddock") raise Exception("Oops, that's his last name") raise Exception("Oops, that's his first name") - self.assertQuerysetEqual(Reporter.objects.all(), []) + self.assertSequenceEqual(Reporter.objects.all(), []) def test_merged_commit_commit(self): with transaction.atomic(): - Reporter.objects.create(first_name="Tintin") + reporter1 = Reporter.objects.create(first_name="Tintin") with transaction.atomic(savepoint=False): - Reporter.objects.create(first_name="Archibald", last_name="Haddock") - self.assertQuerysetEqual( - Reporter.objects.all(), - ['', ''] - ) + reporter2 = Reporter.objects.create(first_name="Archibald", last_name="Haddock") + self.assertSequenceEqual(Reporter.objects.all(), [reporter2, reporter1]) def test_merged_commit_rollback(self): with transaction.atomic(): @@ -130,7 +124,7 @@ class AtomicTests(TransactionTestCase): Reporter.objects.create(first_name="Haddock") raise Exception("Oops, that's his last name") # Writes in the outer block are rolled back too. - self.assertQuerysetEqual(Reporter.objects.all(), []) + self.assertSequenceEqual(Reporter.objects.all(), []) def test_merged_rollback_commit(self): with self.assertRaisesMessage(Exception, "Oops"): @@ -139,7 +133,7 @@ class AtomicTests(TransactionTestCase): with transaction.atomic(savepoint=False): Reporter.objects.create(last_name="Haddock") raise Exception("Oops, that's his first name") - self.assertQuerysetEqual(Reporter.objects.all(), []) + self.assertSequenceEqual(Reporter.objects.all(), []) def test_merged_rollback_rollback(self): with self.assertRaisesMessage(Exception, "Oops"): @@ -150,25 +144,25 @@ class AtomicTests(TransactionTestCase): Reporter.objects.create(first_name="Haddock") raise Exception("Oops, that's his last name") raise Exception("Oops, that's his first name") - self.assertQuerysetEqual(Reporter.objects.all(), []) + self.assertSequenceEqual(Reporter.objects.all(), []) def test_reuse_commit_commit(self): atomic = transaction.atomic() with atomic: - Reporter.objects.create(first_name="Tintin") + reporter1 = Reporter.objects.create(first_name="Tintin") with atomic: - Reporter.objects.create(first_name="Archibald", last_name="Haddock") - self.assertQuerysetEqual(Reporter.objects.all(), ['', '']) + reporter2 = Reporter.objects.create(first_name="Archibald", last_name="Haddock") + self.assertSequenceEqual(Reporter.objects.all(), [reporter2, reporter1]) def test_reuse_commit_rollback(self): atomic = transaction.atomic() with atomic: - Reporter.objects.create(first_name="Tintin") + reporter = Reporter.objects.create(first_name="Tintin") with self.assertRaisesMessage(Exception, "Oops"): with atomic: Reporter.objects.create(first_name="Haddock") raise Exception("Oops, that's his last name") - self.assertQuerysetEqual(Reporter.objects.all(), ['']) + self.assertSequenceEqual(Reporter.objects.all(), [reporter]) def test_reuse_rollback_commit(self): atomic = transaction.atomic() @@ -178,7 +172,7 @@ class AtomicTests(TransactionTestCase): with atomic: Reporter.objects.create(last_name="Haddock") raise Exception("Oops, that's his first name") - self.assertQuerysetEqual(Reporter.objects.all(), []) + self.assertSequenceEqual(Reporter.objects.all(), []) def test_reuse_rollback_rollback(self): atomic = transaction.atomic() @@ -190,7 +184,7 @@ class AtomicTests(TransactionTestCase): Reporter.objects.create(first_name="Haddock") raise Exception("Oops, that's his last name") raise Exception("Oops, that's his first name") - self.assertQuerysetEqual(Reporter.objects.all(), []) + self.assertSequenceEqual(Reporter.objects.all(), []) def test_force_rollback(self): with transaction.atomic(): @@ -198,11 +192,11 @@ class AtomicTests(TransactionTestCase): # atomic block shouldn't rollback, but force it. self.assertFalse(transaction.get_rollback()) transaction.set_rollback(True) - self.assertQuerysetEqual(Reporter.objects.all(), []) + self.assertSequenceEqual(Reporter.objects.all(), []) def test_prevent_rollback(self): with transaction.atomic(): - Reporter.objects.create(first_name="Tintin") + reporter = Reporter.objects.create(first_name="Tintin") sid = transaction.savepoint() # trigger a database error inside an inner atomic without savepoint with self.assertRaises(DatabaseError): @@ -214,7 +208,7 @@ class AtomicTests(TransactionTestCase): self.assertTrue(transaction.get_rollback()) transaction.set_rollback(False) transaction.savepoint_rollback(sid) - self.assertQuerysetEqual(Reporter.objects.all(), ['']) + self.assertSequenceEqual(Reporter.objects.all(), [reporter]) class AtomicInsideTransactionTests(AtomicTests): @@ -269,11 +263,11 @@ class AtomicMergeTests(TransactionTestCase): self.assertEqual(Reporter.objects.count(), 3) transaction.set_rollback(True) # The first block has a savepoint and must roll back. - self.assertQuerysetEqual(Reporter.objects.all(), []) + self.assertSequenceEqual(Reporter.objects.all(), []) def test_merged_inner_savepoint_rollback(self): with transaction.atomic(): - Reporter.objects.create(first_name="Tintin") + reporter = Reporter.objects.create(first_name="Tintin") with transaction.atomic(): Reporter.objects.create(first_name="Archibald", last_name="Haddock") with self.assertRaisesMessage(Exception, "Oops"): @@ -288,7 +282,7 @@ class AtomicMergeTests(TransactionTestCase): transaction.set_rollback(True) # The second block has a savepoint and must roll back. self.assertEqual(Reporter.objects.count(), 1) - self.assertQuerysetEqual(Reporter.objects.all(), ['']) + self.assertSequenceEqual(Reporter.objects.all(), [reporter]) @skipUnlessDBFeature('uses_savepoints')