# in method of TestCase subclass -----------------------------------
user1 = User.objects.create_user(username='user1',
email='us...@test.com', password='password')
user2 = User.objects.create_user(username='user2',
email='us...@test.com', password='password')
self.assertItemsEqual(User.objects.all(), [user1, user2])
#-------------------------------------------------------------------
However the code raise ``AssertionError: Sequences differ: ...`` in
Django 1.3 + Python 2.6 or Django 1.3 + Python 2.7 + unittest2. (well
but I have no idea why the code above works with Django 1.3 + Python 2.7
without unittest2)
This happen because unittest2 or whatever does ``sorted(expected_seq)``
in ``assertItemsEqual`` method but they don't know how to sort the
instances of model class. To solve this problem, I simply add
``__cmp__`` method to Model class like::
# somewhere but called after Django has correctly configured -------
from django.db.models import Model
if not hasattr(Model, '__cmp__'):
Model.__cmp__ = lambda self, other: cmp(self._get_pk_val(),
other._get_pk_val())
#-------------------------------------------------------------------
But it is too annoying to call this patch in every library which use
``assertItemsEqual`` for testing. So I wander if official django's model
class has ``__cmp__`` method in default.
Thanks.
Since 1.3 Django ships with unittest2 library (see
django.utils.unittest), so if there are no
other versions of unittest2 installed, it will use that (which is a
verbatim copy of unittest2==0.5.1).
Python 2.7 seems to have a bit different implementation of that
method, but it uses things like Counter.
>
> This happen because unittest2 or whatever does ``sorted(expected_seq)``
> in ``assertItemsEqual`` method but they don't know how to sort the
> instances of model class.
Actually, assertItemsEqual handles unorderable and unhashable items,
if you take a look at it's source code. The py2.7 version should too.
Didn't have time to check this, but it looks like a bug in unittest2.
> To solve this problem, I simply add
> ``__cmp__`` method to Model class like::
>
> # somewhere but called after Django has correctly configured -------
> from django.db.models import Model
>
> if not hasattr(Model, '__cmp__'):
> Model.__cmp__ = lambda self, other: cmp(self._get_pk_val(),
> other._get_pk_val())
> #-------------------------------------------------------------------
>
Apart from __cmp__ being deprecated, this isn't really correct even
for testing (the model can have an UUIDField as it's pk instead of a
sequential integer).
For making assertions about QuerySets, there already is
assertQuerysetEqual(), so -1 on adding __cmp__ to Model.
--
Łukasz Rekucki