mirror of https://github.com/django/django.git
Fixed #19462 -- Made assertQuerysetEqual detect undefined ordering
If there are more than one values to compare against and the qs isn't ordered then assertQuerysetEqual will raise a ValueError.
This commit is contained in:
parent
6ed6a18a03
commit
088d3bc2f8
|
@ -767,6 +767,12 @@ class TransactionTestCase(SimpleTestCase):
|
|||
items = six.moves.map(transform, qs)
|
||||
if not ordered:
|
||||
return self.assertEqual(set(items), set(values))
|
||||
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:
|
||||
raise ValueError("Trying to compare non-ordered queryset "
|
||||
"against more than one ordered values")
|
||||
return self.assertEqual(list(items), values)
|
||||
|
||||
def assertNumQueries(self, num, func=None, *args, **kwargs):
|
||||
|
|
|
@ -23,6 +23,11 @@ Minor features
|
|||
* Authentication backends can raise ``PermissionDenied`` to immediately fail
|
||||
the authentication chain.
|
||||
|
||||
* The ``assertQuerysetEqual()`` now checks for undefined order and raises
|
||||
``ValueError`` if undefined order is spotted. The order is seen as
|
||||
undefined if the given ``QuerySet`` isn't ordered and there are more than
|
||||
one ordered values to compare against.
|
||||
|
||||
Backwards incompatible changes in 1.6
|
||||
=====================================
|
||||
|
||||
|
|
|
@ -1770,6 +1770,11 @@ your test suite.
|
|||
via an explicit ``order_by()`` call on the queryset prior to
|
||||
comparison.
|
||||
|
||||
.. versionchanged:: 1.6
|
||||
The method now checks for undefined order and raises ``ValueError``
|
||||
if undefined order is spotted. The ordering is seen as undefined if
|
||||
the given ``qs`` isn't ordered and the comparison is against more
|
||||
than one ordered values.
|
||||
|
||||
.. method:: TestCase.assertNumQueries(num, func, *args, **kwargs)
|
||||
|
||||
|
|
|
@ -158,6 +158,7 @@ class ExpressionsTests(TestCase):
|
|||
"Max Mustermann",
|
||||
],
|
||||
lambda c: six.text_type(c.point_of_contact),
|
||||
ordered=False
|
||||
)
|
||||
|
||||
c = Company.objects.all()[0]
|
||||
|
@ -170,7 +171,8 @@ class ExpressionsTests(TestCase):
|
|||
"Foobar Ltd.",
|
||||
"Test GmbH",
|
||||
],
|
||||
lambda c: c.name
|
||||
lambda c: c.name,
|
||||
ordered=False
|
||||
)
|
||||
|
||||
Company.objects.exclude(
|
||||
|
|
|
@ -77,7 +77,8 @@ class CustomField(TestCase):
|
|||
"12",
|
||||
"23",
|
||||
],
|
||||
lambda m: str(m.data)
|
||||
lambda m: str(m.data),
|
||||
ordered=False
|
||||
)
|
||||
|
||||
def test_field_subclassing(self):
|
||||
|
|
|
@ -96,8 +96,8 @@ class FixtureLoadingTests(TestCase):
|
|||
management.call_command('loaddata', 'fixture6.json', verbosity=0, commit=False)
|
||||
self.assertQuerysetEqual(Tag.objects.all(), [
|
||||
'<Tag: <Article: Copyright is fine the way it is> tagged "copyright">',
|
||||
'<Tag: <Article: Copyright is fine the way it is> tagged "law">'
|
||||
])
|
||||
'<Tag: <Article: Copyright is fine the way it is> tagged "law">',
|
||||
], ordered=False)
|
||||
|
||||
# Load fixture 7, XML file with dynamic ContentType fields. Testing ManyToOne.
|
||||
management.call_command('loaddata', 'fixture7.xml', verbosity=0, commit=False)
|
||||
|
@ -105,8 +105,8 @@ class FixtureLoadingTests(TestCase):
|
|||
'<Tag: <Article: Copyright is fine the way it is> tagged "copyright">',
|
||||
'<Tag: <Article: Copyright is fine the way it is> tagged "legal">',
|
||||
'<Tag: <Article: Django conquers world!> tagged "django">',
|
||||
'<Tag: <Article: Django conquers world!> tagged "world domination">'
|
||||
])
|
||||
'<Tag: <Article: Django conquers world!> tagged "world domination">',
|
||||
], ordered=False)
|
||||
|
||||
# Load fixture 8, JSON file with dynamic Permission fields. Testing ManyToMany.
|
||||
management.call_command('loaddata', 'fixture8.json', verbosity=0, commit=False)
|
||||
|
@ -114,7 +114,7 @@ class FixtureLoadingTests(TestCase):
|
|||
'<Visa: Django Reinhardt Can add user, Can change user, Can delete user>',
|
||||
'<Visa: Stephane Grappelli Can add user>',
|
||||
'<Visa: Prince >'
|
||||
])
|
||||
], ordered=False)
|
||||
|
||||
# Load fixture 9, XML file with dynamic Permission fields. Testing ManyToMany.
|
||||
management.call_command('loaddata', 'fixture9.xml', verbosity=0, commit=False)
|
||||
|
@ -122,7 +122,7 @@ class FixtureLoadingTests(TestCase):
|
|||
'<Visa: Django Reinhardt Can add user, Can change user, Can delete user>',
|
||||
'<Visa: Stephane Grappelli Can add user, Can delete user>',
|
||||
'<Visa: Artist formerly known as "Prince" Can change user>'
|
||||
])
|
||||
], ordered=False)
|
||||
|
||||
self.assertQuerysetEqual(Book.objects.all(), [
|
||||
'<Book: Achieving self-awareness of Python programs>',
|
||||
|
@ -280,7 +280,7 @@ class FixtureLoadingTests(TestCase):
|
|||
self.assertQuerysetEqual(Tag.objects.all(), [
|
||||
'<Tag: <Article: Time to reform copyright> tagged "copyright">',
|
||||
'<Tag: <Article: Time to reform copyright> tagged "law">'
|
||||
])
|
||||
], ordered=False)
|
||||
|
||||
# Dump the current contents of the database as a JSON fixture
|
||||
self._dumpdata_assert(['fixtures'], '[{"pk": 1, "model": "fixtures.category", "fields": {"description": "Latest news stories", "title": "News Stories"}}, {"pk": 2, "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16T12:00:00"}}, {"pk": 3, "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16T13:00:00"}}, {"pk": 1, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "copyright", "tagged_id": 3}}, {"pk": 2, "model": "fixtures.tag", "fields": {"tagged_type": ["fixtures", "article"], "name": "law", "tagged_id": 3}}, {"pk": 1, "model": "fixtures.person", "fields": {"name": "Django Reinhardt"}}, {"pk": 2, "model": "fixtures.person", "fields": {"name": "Stephane Grappelli"}}, {"pk": 3, "model": "fixtures.person", "fields": {"name": "Prince"}}, {"pk": 10, "model": "fixtures.book", "fields": {"name": "Achieving self-awareness of Python programs", "authors": []}}]', natural_keys=True)
|
||||
|
|
|
@ -169,8 +169,8 @@ class GenericRelationsTests(TestCase):
|
|||
# Filtering works
|
||||
self.assertQuerysetEqual(tiger.comparisons.filter(comparative="cooler"), [
|
||||
"<Comparison: tiger is cooler than cheetah>",
|
||||
"<Comparison: tiger is cooler than bear>"
|
||||
])
|
||||
"<Comparison: tiger is cooler than bear>",
|
||||
], ordered=False)
|
||||
|
||||
# Filtering and deleting works
|
||||
subjective = ["cooler"]
|
||||
|
@ -178,7 +178,7 @@ class GenericRelationsTests(TestCase):
|
|||
self.assertQuerysetEqual(Comparison.objects.all(), [
|
||||
"<Comparison: cheetah is faster than tiger>",
|
||||
"<Comparison: tiger is stronger than cheetah>"
|
||||
])
|
||||
], ordered=False)
|
||||
|
||||
# If we delete cheetah, Comparisons with cheetah as 'first_obj' will be
|
||||
# deleted since Animal has an explicit GenericRelation to Comparison
|
||||
|
|
|
@ -28,7 +28,8 @@ class RecursiveM2MTests(TestCase):
|
|||
"Chuck",
|
||||
"David"
|
||||
],
|
||||
attrgetter("name")
|
||||
attrgetter("name"),
|
||||
ordered=False
|
||||
)
|
||||
# Who is friends with Bill?
|
||||
self.assertQuerysetEqual(
|
||||
|
@ -43,7 +44,8 @@ class RecursiveM2MTests(TestCase):
|
|||
"Anne",
|
||||
"David"
|
||||
],
|
||||
attrgetter("name")
|
||||
attrgetter("name"),
|
||||
ordered=False
|
||||
)
|
||||
# Who is friends with David?
|
||||
self.assertQuerysetEqual(
|
||||
|
@ -51,7 +53,8 @@ class RecursiveM2MTests(TestCase):
|
|||
"Anne",
|
||||
"Chuck",
|
||||
],
|
||||
attrgetter("name")
|
||||
attrgetter("name"),
|
||||
ordered=False
|
||||
)
|
||||
# Bill is already friends with Anne - add Anne again, but in the
|
||||
# reverse direction
|
||||
|
@ -64,7 +67,8 @@ class RecursiveM2MTests(TestCase):
|
|||
"Chuck",
|
||||
"David",
|
||||
],
|
||||
attrgetter("name")
|
||||
attrgetter("name"),
|
||||
ordered=False
|
||||
)
|
||||
# Who is friends with Bill?
|
||||
self.assertQuerysetEqual(
|
||||
|
@ -81,7 +85,8 @@ class RecursiveM2MTests(TestCase):
|
|||
"Chuck",
|
||||
"David",
|
||||
],
|
||||
attrgetter("name")
|
||||
attrgetter("name"),
|
||||
ordered=False
|
||||
)
|
||||
# Who is friends with Bill?
|
||||
self.assertQuerysetEqual(
|
||||
|
@ -125,7 +130,8 @@ class RecursiveM2MTests(TestCase):
|
|||
"Chuck",
|
||||
"David",
|
||||
],
|
||||
attrgetter("name")
|
||||
attrgetter("name"),
|
||||
ordered=False
|
||||
)
|
||||
# Who is stalking Anne?
|
||||
self.assertQuerysetEqual(
|
||||
|
@ -172,7 +178,8 @@ class RecursiveM2MTests(TestCase):
|
|||
"Anne",
|
||||
"Chuck",
|
||||
],
|
||||
attrgetter("name")
|
||||
attrgetter("name"),
|
||||
ordered=False
|
||||
)
|
||||
# Bill is already being stalked by Anne - add Anne again, but in the
|
||||
# reverse direction
|
||||
|
@ -184,7 +191,8 @@ class RecursiveM2MTests(TestCase):
|
|||
"Chuck",
|
||||
"David",
|
||||
],
|
||||
attrgetter("name")
|
||||
attrgetter("name"),
|
||||
ordered=False
|
||||
)
|
||||
# Who is stalking Anne?
|
||||
self.assertQuerysetEqual(
|
||||
|
@ -215,7 +223,8 @@ class RecursiveM2MTests(TestCase):
|
|||
"Chuck",
|
||||
"David",
|
||||
],
|
||||
attrgetter("name")
|
||||
attrgetter("name"),
|
||||
ordered=False
|
||||
)
|
||||
# Who is stalking Anne?
|
||||
self.assertQuerysetEqual(
|
||||
|
|
|
@ -267,7 +267,9 @@ class ManyToOneTests(TestCase):
|
|||
["<Reporter: John Smith>"])
|
||||
self.assertQuerysetEqual(
|
||||
Reporter.objects.filter(article__headline__startswith='T'),
|
||||
["<Reporter: John Smith>", "<Reporter: John Smith>"])
|
||||
["<Reporter: John Smith>", "<Reporter: John Smith>"],
|
||||
ordered=False
|
||||
)
|
||||
self.assertQuerysetEqual(
|
||||
Reporter.objects.filter(article__headline__startswith='T').distinct(),
|
||||
["<Reporter: John Smith>"])
|
||||
|
@ -285,7 +287,9 @@ class ManyToOneTests(TestCase):
|
|||
"<Reporter: John Smith>",
|
||||
"<Reporter: John Smith>",
|
||||
"<Reporter: John Smith>",
|
||||
])
|
||||
],
|
||||
ordered=False
|
||||
)
|
||||
self.assertQuerysetEqual(
|
||||
Reporter.objects.filter(article__reporter__first_name__startswith='John').distinct(),
|
||||
["<Reporter: John Smith>"])
|
||||
|
|
|
@ -1044,9 +1044,12 @@ class OldFormForXTests(TestCase):
|
|||
self.assertQuerysetEqual(f.clean([c1.id]), ["Entertainment"])
|
||||
self.assertQuerysetEqual(f.clean([c2.id]), ["It's a test"])
|
||||
self.assertQuerysetEqual(f.clean([str(c1.id)]), ["Entertainment"])
|
||||
self.assertQuerysetEqual(f.clean([str(c1.id), str(c2.id)]), ["Entertainment", "It's a test"])
|
||||
self.assertQuerysetEqual(f.clean([c1.id, str(c2.id)]), ["Entertainment", "It's a test"])
|
||||
self.assertQuerysetEqual(f.clean((c1.id, str(c2.id))), ["Entertainment", "It's a test"])
|
||||
self.assertQuerysetEqual(f.clean([str(c1.id), str(c2.id)]), ["Entertainment", "It's a test"],
|
||||
ordered=False)
|
||||
self.assertQuerysetEqual(f.clean([c1.id, str(c2.id)]), ["Entertainment", "It's a test"],
|
||||
ordered=False)
|
||||
self.assertQuerysetEqual(f.clean((c1.id, str(c2.id))), ["Entertainment", "It's a test"],
|
||||
ordered=False)
|
||||
with self.assertRaises(ValidationError):
|
||||
f.clean(['100'])
|
||||
with self.assertRaises(ValidationError):
|
||||
|
|
|
@ -26,12 +26,13 @@ class ExpressionsRegressTests(TestCase):
|
|||
same object.
|
||||
"""
|
||||
self.assertQuerysetEqual(
|
||||
Number.objects.all(),
|
||||
[
|
||||
'<Number: -1, -1.000>',
|
||||
'<Number: 42, 42.000>',
|
||||
'<Number: 1337, 1337.000>'
|
||||
]
|
||||
Number.objects.all(),
|
||||
[
|
||||
'<Number: -1, -1.000>',
|
||||
'<Number: 42, 42.000>',
|
||||
'<Number: 1337, 1337.000>'
|
||||
],
|
||||
ordered=False
|
||||
)
|
||||
|
||||
def test_increment_value(self):
|
||||
|
@ -44,12 +45,13 @@ class ExpressionsRegressTests(TestCase):
|
|||
2)
|
||||
|
||||
self.assertQuerysetEqual(
|
||||
Number.objects.all(),
|
||||
[
|
||||
'<Number: -1, -1.000>',
|
||||
'<Number: 43, 42.000>',
|
||||
'<Number: 1338, 1337.000>'
|
||||
]
|
||||
Number.objects.all(),
|
||||
[
|
||||
'<Number: -1, -1.000>',
|
||||
'<Number: 43, 42.000>',
|
||||
'<Number: 1338, 1337.000>'
|
||||
],
|
||||
ordered=False
|
||||
)
|
||||
|
||||
def test_filter_not_equals_other_field(self):
|
||||
|
@ -62,11 +64,12 @@ class ExpressionsRegressTests(TestCase):
|
|||
.update(integer=F('integer') + 1),
|
||||
2)
|
||||
self.assertQuerysetEqual(
|
||||
Number.objects.exclude(float=F('integer')),
|
||||
[
|
||||
'<Number: 43, 42.000>',
|
||||
'<Number: 1338, 1337.000>'
|
||||
]
|
||||
Number.objects.exclude(float=F('integer')),
|
||||
[
|
||||
'<Number: 43, 42.000>',
|
||||
'<Number: 1338, 1337.000>'
|
||||
],
|
||||
ordered=False
|
||||
)
|
||||
|
||||
def test_complex_expressions(self):
|
||||
|
|
|
@ -58,13 +58,15 @@ class ExtraRegressTests(TestCase):
|
|||
('First Revision', 'First Revision'),
|
||||
('Second Revision', 'First Revision'),
|
||||
],
|
||||
transform=lambda r: (r.title, r.base.title)
|
||||
transform=lambda r: (r.title, r.base.title),
|
||||
ordered=False
|
||||
)
|
||||
|
||||
# Following queryset should return the most recent revision:
|
||||
self.assertQuerysetEqual(qs & qs2,
|
||||
[('Second Revision', 'First Revision')],
|
||||
transform=lambda r: (r.title, r.base.title)
|
||||
transform=lambda r: (r.title, r.base.title),
|
||||
ordered=False
|
||||
)
|
||||
|
||||
def test_extra_stay_tied(self):
|
||||
|
@ -342,5 +344,6 @@ class ExtraRegressTests(TestCase):
|
|||
TestObject.objects.extra(
|
||||
where=["first = 'a' OR second = 'a'", "third = 'a'"],
|
||||
),
|
||||
['<TestObject: TestObject: a,a,a>', '<TestObject: TestObject: b,a,a>']
|
||||
['<TestObject: TestObject: a,a,a>', '<TestObject: TestObject: b,a,a>'],
|
||||
ordered=False
|
||||
)
|
||||
|
|
|
@ -74,7 +74,7 @@ class M2MRegressionTests(TestCase):
|
|||
c1.tags = [t1, t2]
|
||||
c1 = TagCollection.objects.get(name='c1')
|
||||
|
||||
self.assertQuerysetEqual(c1.tags.all(), ["<Tag: t1>", "<Tag: t2>"])
|
||||
self.assertQuerysetEqual(c1.tags.all(), ["<Tag: t1>", "<Tag: t2>"], ordered=False)
|
||||
self.assertQuerysetEqual(t1.tag_collections.all(), ["<TagCollection: c1>"])
|
||||
|
||||
def test_manager_class_caching(self):
|
||||
|
|
|
@ -28,7 +28,8 @@ class M2MThroughTestCase(TestCase):
|
|||
bob.group_set.all(), [
|
||||
"<Group: Rock>",
|
||||
"<Group: Roll>",
|
||||
]
|
||||
],
|
||||
ordered=False
|
||||
)
|
||||
|
||||
self.assertQuerysetEqual(
|
||||
|
@ -51,7 +52,8 @@ class M2MThroughTestCase(TestCase):
|
|||
frank.group_set.all(), [
|
||||
"<Group: Rock>",
|
||||
"<Group: Roll>",
|
||||
]
|
||||
],
|
||||
ordered=False
|
||||
)
|
||||
|
||||
self.assertQuerysetEqual(
|
||||
|
@ -190,7 +192,8 @@ class ToFieldThroughTests(TestCase):
|
|||
self.driver.car_set._add_items('driver', 'car', car2)
|
||||
self.assertQuerysetEqual(
|
||||
self.driver.car_set.all(),
|
||||
["<Car: Toyota>", "<Car: Honda>"]
|
||||
["<Car: Toyota>", "<Car: Honda>"],
|
||||
ordered=False
|
||||
)
|
||||
|
||||
def test_add_null_reverse(self):
|
||||
|
|
|
@ -61,7 +61,8 @@ class ManagersRegressionTests(TestCase):
|
|||
self.assertQuerysetEqual(Child4.manager1.all(), [
|
||||
"<Child4: d1>",
|
||||
"<Child4: f1>"
|
||||
]
|
||||
],
|
||||
ordered=False
|
||||
)
|
||||
self.assertQuerysetEqual(Child5._default_manager.all(), ["<Child5: fred>"])
|
||||
self.assertQuerysetEqual(Child6._default_manager.all(), ["<Child6: f1>"])
|
||||
|
|
|
@ -71,7 +71,8 @@ class ModelTests(TestCase):
|
|||
datetime.date(1999, 12, 31),
|
||||
datetime.date(1998, 12, 31),
|
||||
],
|
||||
attrgetter("when")
|
||||
attrgetter("when"),
|
||||
ordered=False
|
||||
)
|
||||
self.assertQuerysetEqual(
|
||||
Party.objects.filter(when__year=1998), [
|
||||
|
@ -85,14 +86,16 @@ class ModelTests(TestCase):
|
|||
datetime.date(1999, 12, 31),
|
||||
datetime.date(1998, 12, 31),
|
||||
],
|
||||
attrgetter("when")
|
||||
attrgetter("when"),
|
||||
ordered=False
|
||||
)
|
||||
self.assertQuerysetEqual(
|
||||
Party.objects.filter(when__month="12"), [
|
||||
datetime.date(1999, 12, 31),
|
||||
datetime.date(1998, 12, 31),
|
||||
],
|
||||
attrgetter("when")
|
||||
attrgetter("when"),
|
||||
ordered=False
|
||||
)
|
||||
self.assertQuerysetEqual(
|
||||
Party.objects.filter(when__year="1998"), [
|
||||
|
|
|
@ -841,11 +841,14 @@ class Queries1Tests(BaseQuerysetTest):
|
|||
"""
|
||||
original_ordering = Tag._meta.ordering
|
||||
Tag._meta.ordering = None
|
||||
self.assertQuerysetEqual(
|
||||
Tag.objects.all(),
|
||||
['<Tag: t1>', '<Tag: t2>', '<Tag: t3>', '<Tag: t4>', '<Tag: t5>'],
|
||||
)
|
||||
Tag._meta.ordering = original_ordering
|
||||
try:
|
||||
self.assertQuerysetEqual(
|
||||
Tag.objects.all(),
|
||||
['<Tag: t1>', '<Tag: t2>', '<Tag: t3>', '<Tag: t4>', '<Tag: t5>'],
|
||||
ordered=False
|
||||
)
|
||||
finally:
|
||||
Tag._meta.ordering = original_ordering
|
||||
|
||||
def test_exclude(self):
|
||||
self.assertQuerysetEqual(
|
||||
|
@ -925,15 +928,18 @@ class Queries2Tests(TestCase):
|
|||
self.assertQuerysetEqual(Number.objects.filter(num__gt=12.1), [])
|
||||
self.assertQuerysetEqual(
|
||||
Number.objects.filter(num__lt=12),
|
||||
['<Number: 4>', '<Number: 8>']
|
||||
['<Number: 4>', '<Number: 8>'],
|
||||
ordered=False
|
||||
)
|
||||
self.assertQuerysetEqual(
|
||||
Number.objects.filter(num__lt=12.0),
|
||||
['<Number: 4>', '<Number: 8>']
|
||||
['<Number: 4>', '<Number: 8>'],
|
||||
ordered=False
|
||||
)
|
||||
self.assertQuerysetEqual(
|
||||
Number.objects.filter(num__lt=12.1),
|
||||
['<Number: 4>', '<Number: 8>', '<Number: 12>']
|
||||
['<Number: 4>', '<Number: 8>', '<Number: 12>'],
|
||||
ordered=False
|
||||
)
|
||||
self.assertQuerysetEqual(
|
||||
Number.objects.filter(num__gte=11.9),
|
||||
|
@ -951,23 +957,28 @@ class Queries2Tests(TestCase):
|
|||
self.assertQuerysetEqual(Number.objects.filter(num__gte=12.9), [])
|
||||
self.assertQuerysetEqual(
|
||||
Number.objects.filter(num__lte=11.9),
|
||||
['<Number: 4>', '<Number: 8>']
|
||||
['<Number: 4>', '<Number: 8>'],
|
||||
ordered=False
|
||||
)
|
||||
self.assertQuerysetEqual(
|
||||
Number.objects.filter(num__lte=12),
|
||||
['<Number: 4>', '<Number: 8>', '<Number: 12>']
|
||||
['<Number: 4>', '<Number: 8>', '<Number: 12>'],
|
||||
ordered=False
|
||||
)
|
||||
self.assertQuerysetEqual(
|
||||
Number.objects.filter(num__lte=12.0),
|
||||
['<Number: 4>', '<Number: 8>', '<Number: 12>']
|
||||
['<Number: 4>', '<Number: 8>', '<Number: 12>'],
|
||||
ordered=False
|
||||
)
|
||||
self.assertQuerysetEqual(
|
||||
Number.objects.filter(num__lte=12.1),
|
||||
['<Number: 4>', '<Number: 8>', '<Number: 12>']
|
||||
['<Number: 4>', '<Number: 8>', '<Number: 12>'],
|
||||
ordered=False
|
||||
)
|
||||
self.assertQuerysetEqual(
|
||||
Number.objects.filter(num__lte=12.9),
|
||||
['<Number: 4>', '<Number: 8>', '<Number: 12>']
|
||||
['<Number: 4>', '<Number: 8>', '<Number: 12>'],
|
||||
ordered=False
|
||||
)
|
||||
|
||||
def test_ticket7411(self):
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
from django.db import models
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Person(models.Model):
|
||||
name = models.CharField(max_length=100)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
|
|
@ -54,6 +54,46 @@ class AssertNumQueriesTests(TestCase):
|
|||
self.assertNumQueries(2, test_func)
|
||||
|
||||
|
||||
class AssertQuerysetEqualTests(TestCase):
|
||||
def setUp(self):
|
||||
self.p1 = Person.objects.create(name='p1')
|
||||
self.p2 = Person.objects.create(name='p2')
|
||||
|
||||
def test_ordered(self):
|
||||
self.assertQuerysetEqual(
|
||||
Person.objects.all().order_by('name'),
|
||||
[repr(self.p1), repr(self.p2)]
|
||||
)
|
||||
|
||||
def test_unordered(self):
|
||||
self.assertQuerysetEqual(
|
||||
Person.objects.all().order_by('name'),
|
||||
[repr(self.p2), repr(self.p1)],
|
||||
ordered=False
|
||||
)
|
||||
|
||||
def test_transform(self):
|
||||
self.assertQuerysetEqual(
|
||||
Person.objects.all().order_by('name'),
|
||||
[self.p1.pk, self.p2.pk],
|
||||
transform=lambda x: x.pk
|
||||
)
|
||||
|
||||
def test_undefined_order(self):
|
||||
# Using an unordered queryset with more than one ordered value
|
||||
# is an error.
|
||||
with self.assertRaises(ValueError):
|
||||
self.assertQuerysetEqual(
|
||||
Person.objects.all(),
|
||||
[repr(self.p1), repr(self.p2)]
|
||||
)
|
||||
# No error for one value.
|
||||
self.assertQuerysetEqual(
|
||||
Person.objects.filter(name='p1'),
|
||||
[repr(self.p1)]
|
||||
)
|
||||
|
||||
|
||||
class AssertNumQueriesContextManagerTests(TestCase):
|
||||
urls = 'regressiontests.test_utils.urls'
|
||||
|
||||
|
|
Loading…
Reference in New Issue