Django: Testen, ob die Seite zur gewünschten URL umgeleitet wurde

73

In meiner Django-App habe ich ein Authentifizierungssystem. Wenn ich mich also nicht anmelde und versuche, auf die persönlichen Daten eines Profils zuzugreifen, werde ich auf eine Anmeldeseite weitergeleitet.

Jetzt muss ich einen Testfall dafür schreiben. Die Antworten der Browser, die ich erhalte, lauten:

GET /myprofile/data/some_id/ HTTP/1.1 302 0
GET /account/login?next=/myprofile/data/some_id/ HTTP/1.1 301 0
GET /account/login?next=/myprofile/data/some_id/ HTTP/1.1 200 6533

Wie schreibe ich meinen Test? Das was ich bisher habe:

self.client.login(user="user", password="passwd")
response = self.client.get('/myprofile/data/some_id/')
self.assertEqual(response.status,200)
self.client.logout()
response = self.client.get('/myprofile/data/some_id/')

Was könnte möglicherweise als nächstes kommen?

Deepankar Bajpeyi
quelle

Antworten:

124

Django 1.4:

https://docs.djangoproject.com/de/1.4/topics/testing/#django.test.TestCase.assertRedirects

Django 2.0:

https://docs.djangoproject.com/de/2.0/topics/testing/tools/#django.test.SimpleTestCase.assertRedirects

SimpleTestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, msg_prefix='', fetch_redirect_response=True)

Gibt an, dass die Antwort einen Status_code- Umleitungsstatus zurückgegeben hat, der an expected_url (einschließlich aller GET- Daten) umgeleitet wurde , und dass die letzte Seite mit target_status_code empfangen wurde .

Wenn Ihre Anfrage das folgende Argument verwendet hat, sind die erwartete URL und der Zielstatuscode die URL und der Statuscode für den Endpunkt der Umleitungskette.

Wenn fetch_redirect_response ist falsch , wird nicht die letzte Seite geladen werden. Da der Testclient keine externen URLs abrufen kann, ist dies besonders nützlich, wenn expected_url nicht Teil Ihrer Django-App ist.

Das Schema wird beim Vergleich zwischen zwei URLs korrekt behandelt. Wenn an dem Ort, an den wir umgeleitet werden, kein Schema angegeben ist, wird das Schema der ursprünglichen Anforderung verwendet. Wenn vorhanden, wird das Schema in expected_url verwendet, mit dem die Vergleiche durchgeführt werden.

imposeren
quelle
54

Sie können der Weiterleitung auch folgen mit:

response = self.client.get('/myprofile/data/some_id/', follow=True)

Dies würde die Benutzererfahrung im Browser widerspiegeln und Aussagen darüber machen, was Sie dort erwarten, wie zum Beispiel:

self.assertContains(response, "You must be logged in", status_code=401)
Zündstrom
quelle
1
Das Erwarten eines bestimmten Seiteninhalts in einem Test ist gefährlich. Ermöglicht es Nicht-Programmierern (Webseiten-Editoren), die Tests unwissentlich zu unterbrechen.
Aliteralmind
31

Sie können überprüfen, response['Location']ob es mit der erwarteten URL übereinstimmt. Überprüfen Sie auch, ob der Statuscode 302 lautet.

luc
quelle
3
Am besten, wenn es einem egal ist, was sein target_status_codewird.
Emyller
Wenn Sie Unit-Tests direkt in den Ansichten durchführen (ohne den Django-Client zu verwenden), ist dies die richtige Antwort.
Aaron D
12

response['Location']existiert nicht in 1.9. Verwenden Sie stattdessen Folgendes:

response = self.client.get('/myprofile/data/some_id/', follow=True)
last_url, status_code = response.redirect_chain[-1]
print(last_url)
Alan Viars
quelle
8
Es ist verfügbar, wenn follow=Truees nicht bereitgestellt wird. Django (jede Version) entfernt keine normalen Antwortheader wie Location. Wann followist True, werden die Weiterleitungen verfolgt und natürlich hat die letzte Antwort keinen LocationHeader.
Amir Ali Akbari
Ich bestätige, dass Amir korrekt ist (Django 1.11.8), wodurch die Umleitung mit self.assertRedirects(oder dem status_code) überprüft und der Umleitungsort überprüft werden kann.
Raffi