2013-04-17 2 views
14

У меня есть очень простой вид следующийсравнивающего querysets в Джанго TestCase

def simple_view(request): 
    documents = request.user.document_set.all() 
    return render(request, 'simple.html', {'documents': documents}) 

Чтобы проверить вышеуказанную точку зрения в моем тестовом случае у меня есть следующий метод, который ошибка вне.

Class SomeTestCase(TestCase): 
    # ... 
    def test_simple_view(self): 
     # ... some other checks 
     docset = self.resonse.context['documents'] 
     self.assertTrue(self.user.document_set.all() == docset) # This line raises an error 
    # ... 

Ошибка, которую я получаю, это AssertionError: False is not true. Я пробовал распечатать оба запроса, и оба они абсолютно идентичны. Зачем ему возвращать False, когда оба объекта идентичны? Есть идеи ?

В настоящее время, чтобы преодолеть это, я использую неприятную хак проверки длины следующим образом:

ds1, ds2 = self.response.context['documents'], self.user.document_set.all() 
self.assertTrue(len([x for x in ds1 if x in ds2]) == len(ds1) == len(ds2)) # Makes sure each entry in ds1 exists in ds2 

ответ

19

Объекты QuerySet не будут идентичны, если они являются результатом различных запросов, даже если они имеют одинаковые значения в их результате (сравните ds1.query и ds2.query).

Если преобразовать запрос установлен в списке первым, вы должны быть в состоянии сделать нормальный сравнение (предполагая, что они имеют одинаковый порядок сортировки, конечно):

self.assertEqual(list(ds1), list(ds2)) 
+0

yup, только что нашел решение. Благодарю. – Amyth

+1

Или немного более лаконично self.assertEqual (list (ds1), list (ds2)) – igniteflow

0

Найдено решение. Нам нужно преобразовать Querysets в отсортированные списки, прежде чем мы сможем их сравнить. Что-то следующее.

Class SomeTestCase(TestCase): 
    # ... 
    def test_simple_view(self): 
     # ... some other checks 
     docset1 = self.resonse.context['documents'] 
     docset2 = self.user.document_set.all() 
     self.assertTrue(list(sorted(docset1)) == len(sorted(docset))) 
    # ... 
6

Эта альтернатива не нужна сортировка:

self.assertQuerysetEqual(qs1, list(qs2), ordered=False) 

assert reference См.

Примечание: Только для django 1.4+.

+0

Пробовал это, но запросы не равны все время (даже если они одинаковы)! Получил это, используя: 'self.assertQuerysetEqual (qs1, map (repr, qs2), ordered = False)'. Из этой темы: http://stackoverflow.com/a/14189017/821594 – stalk

+0

@stalk Я действительно не знаю, почему ... для сравнения по умолчанию предполагается использовать 'repr()'. И если оба quesysets равны, ожидается, что рев будет одинаковым, не так ли? –

+2

Глядя на [docs] (https://docs.djangoproject.com/en/1.5/topics/testing/overview/#django.test.TestCase.assertQuerysetEqual), я подумал, что ваш пример будет работать. Но это не так ... Похоже, что функция 'repr' func применяется только к первому набору запросов без списка, а для второго списка он должен быть применен явно. С django 1.4.5: 'qs1 = M.objects.all(); qs2 = M.objects.all() # (то же самое) ',' self.assertQuerysetEqual (qs1, list (qs2), ordered = False) '<- fail; 'self.assertQuerysetEqual (qs1, map (repr, qs2), упорядоченный = False)' <- проходит; – stalk

Смежные вопросы