2013-04-17 13 views
14

Ho una visione molto semplice come segueconfrontando querysets in django testCase

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

Per testare la vista sopra nel mio caso di test ho il seguente metodo che gli errori fuori.

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

L'errore che ottengo è AssertionError: False is not true. Ho provato a stampare entrambi i set di query ed entrambi sono assolutamente identici. Perché dovrebbe restituire False quando entrambi gli oggetti sono identici? Qualche idea ?

Attualmente per superare questo, sto usando una brutta hack di lunghezze di controllo come segue:

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 

risposta

19

Gli oggetti set di query non saranno identici se sono il risultato di query diverse, anche se hanno gli stessi valori nel loro risultato (confronta ds1.query e ds2.query).

Se si converte la query impostata su un primo elenco, si dovrebbe essere in grado di fare un confronto normale (ammesso che ne abbiano lo stesso ordinamento del corso):

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

sì, ho appena trovato la soluzione. Grazie. – Amyth

+1

O leggermente più sinteticamente self.assertEqual (lista (ds1), lista (ds2)) – igniteflow

0

trovato una soluzione. Dobbiamo convertire Querysets in elenchi ordinati prima di poterli confrontare. Qualcosa come segue.

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

Questa alternativa non ha bisogno di smistamento:

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

Vedere le assert reference.

Nota: Solo per django 1.4+.

+0

Provato questo, ma i querysets non sono uguali per tutto il tempo (anche se sono gli stessi)! Ho funzionato usando: 'self.assertQuerysetEqual (qs1, map (repr, qs2), ordered = False)'. Da questo thread: http://stackoverflow.com/a/14189017/821594 – stalk

+0

@stalk Non so davvero perché ... si suppone che utilizzi 'repr()' per confrontare per impostazione predefinita. E se entrambi i questionari sono uguali, il repr dovrebbe essere lo stesso, giusto? –

+2

Guardando [docs] (https://docs.djangoproject.com/en/1.5/topics/testing/overview/#django.test.TestCase.assertQuerysetEqual) ho pensato che il tuo esempio funzionasse. Ma non è così ... Sembra che 'repr' func sia applicato solo al primo queryset non-list, e per il secondo elenco deve essere esplicitamente applacciato. Con django 1.4.5: 'qs1 = M.objects.all(); qs2 = M.objects.all() # (lo stesso) ',' self.assertQuerysetEqual (qs1, list (qs2), ordered = False) '<- fallisce; 'self.assertQuerysetEqual (qs1, map (repr, qs2), ordered = False)' <- passa; – stalk