2013-04-17 9 views
14

Mam bardzo prosty pogląd następującoporównujące querysets w Django TESTCASE

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

Aby przetestować powyższy pogląd w moim przypadku testowego Mam następującą metodę, która się błędy.

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 
    # ... 

Błąd, który otrzymałem, to AssertionError: False is not true. Próbowałem wydrukować oba zapytania i oba są absolutnie identyczne. Dlaczego miałby powrócić False, gdy oba obiekty są identyczne? Jakieś pomysły ?

Obecnie do przezwyciężenia tego, używam paskudny siekać długości sprawdzanie następująco:

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 

Odpowiedz

19

Obiekty QuerySet nie będą identyczne, jeśli są one wynikiem różnych zapytań, nawet jeśli mają te same wartości w ich wyniku (porównaj ds1.query i ds2.query).

Jeśli konwertować kwerendy ustawiony na liście pierwszy, powinieneś być w stanie zrobić normalne porównanie (zakładając, że mają ten sam porządek oczywiście):

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

tak, właśnie znalazłem rozwiązanie. Dzięki. – Amyth

+1

Lub nieznacznie bardziej zwięźle self.assertEqual (lista (ds1), lista (ds2)) – igniteflow

0

znalazł rozwiązanie. Musimy przekonwertować Querysets na posortowane listy, zanim będziemy mogli je porównać. Coś w następujący sposób.

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

Ta alternatywa nie musi Sortowanie:

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

Zobacz assert reference.

Uwaga: Tylko dla django 1.4+.

+0

Próbowałem tego, ale querysets nie są równe przez cały czas (nawet jeśli są takie same)! Udało się to za pomocą: 'self.assertQuerysetEqual (qs1, map (repr, qs2), ordered = False)'. Z tego wątku: http://stackoverflow.com/a/14189017/821594 – stalk

+0

@stalk Naprawdę nie wiem dlaczego ... powinien domyślnie używać 'repr()'. A jeśli oba quesysety są równe, oczekuje się, że repr będzie taki sam, prawda? –

+2

Patrząc na [docs] (https://docs.djangoproject.com/en/1.5/topics/testing/overview/#django.test.TestCase.assertQuerysetEqual) pomyślałem, że twój przykład zadziała. Ale to nie ... Wygląda na to, że 'repr' func jest stosowane tylko do pierwszego kwerendy nie-listowej, a dla drugiej listy musi być jawnie zastosowane. Z django 1.4.5: 'qs1 = M.objects.all(); qs2 = M.objects.all() # (to samo) ',' self.assertQuerysetEqual (qs1, list (qs2), ordered = False) '<- zawiedzie; 'self.assertQuerysetEqual (qs1, map (repr, qs2), ordered = False)' <- przechodzi; – stalk

Powiązane problemy