Is there a way to check that two lists of objects are equal in django tests.
lets say I have some model:
class Tag(models.Model):
slug = models.SlugField(max_length=50, unique=True)
def __unicode__(self):
return self.slug
and I run this simple test:
def test_equal_list_fail(self):
tag_list = []
for tag in ['a', 'b', 'c']:
tag_list.append(Tag.objects.create(slug=tag))
tags = Tag.objects.all()
self.assertEqual(tag_list, tags)
this fails with:
======================================================================
FAIL: test_equal_list_fail (userAccount.tests.ProfileTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "path/to/tests.py", line 155, in test_equal_list_fail
self.assertEqual(tag_list, tags)
AssertionError: [<Tag: a>, <Tag: b>, <Tag: c>] != [<Tag: a>, <Tag: b>, <Tag: c>]
----------------------------------------------------------------------
this will work:
def test_equal_list_passes(self):
tag_list = []
for tag in ['a', 'b', 'c']:
tag_list.append(Tag.objects.create(slug=tag))
tags = Tag.objects.all()
for tag_set in zip(tags, tag_list):
self.assertEqual(*tag_set)
However, This fails:
def test_equal_list_fail(self):
tag_list = []
for tag in ['a', 'b', 'c']:
tag_list.append(Tag.objects.create(slug=tag))
tags = Tag.objects.all()
for tag_set in zip(tags, tag_list):
print "\n"
print tag_set[0].slug + "'s pk is %s" % tag_set[0].pk
print tag_set[1].slug + "'s pk is %s" % tag_set[1].pk
print "\n"
self.assertIs(*tag_set)
with:
Creating test database for alias 'default'...
.......
a's pk is 1
a's pk is 1
F.
======================================================================
FAIL: test_equal_list_fail (userAccount.tests.ProfileTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "path/to/tests.py", line 160, in test_equal_list_fail
self.assertIs(*tag_set)
AssertionError: <Tag: a> is not <Tag: a>
Is this expected behavior?
Edit in response to comment
This type of comparison works:
class Obj:
def __init__(self, x):
self.x = x
>>> one = Obj(1)
>>> two = Obj(2)
>>> a = [one, two]
>>> b = [one, two]
>>> a == b
True
Why is the test failing for the other arrays?
use: assertSequenceEqual
Because, in this case, tags = Tag.objects.all()
generates a django.db.models.query.QuerySet
where as tag_list.append(...)
creates a list.
Other options in different situations are:
<Tag: a> is not <Tag: a>
The tags are the same model, but they've been loaded into different places in memory
for tag_set in zip(tags, tag_list):
print "\n"
print tag_set[0].slug + "'s pk is %s" % tag_set[0].pk + ' id is: ' + id(tag_set[0])
print tag_set[1].slug + "'s pk is %s" % tag_set[1].pk + ' id is: ' + id(tag_set[1])
print "\n"
self.assertIs(*tag_set)
returns
.......
a's pk is 1 id is: 4522000208
a's pk is 1 id is: 4522228112
F.
Therefore, is
will retrun False
I think what you want to test is if the tags created have the same slugs as those in your test list.
For that, fetch only the slug as a list with values_list
, and then compare that:
assertEqual(Tag.objects.values_list('slug', flat=True), ['a','b','c'])
I have to say, this isn't quite a useful test because you are checking django orm functionality, which has already been tested quite well.
Your tests should check for specifics of your own application.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With