Wie soll ich Tests für Formulare in Django schreiben?

109

Ich möchte Anfragen an meine Ansichten in Django simulieren, wenn ich Tests schreibe. Dies dient hauptsächlich zum Testen der Formulare. Hier ist ein Ausschnitt einer einfachen Testanfrage:

from django.tests import TestCase

class MyTests(TestCase):
    def test_forms(self):
        response = self.client.post("/my/form/", {'something':'something'})
        self.assertEqual(response.status_code, 200) # we get our page back with an error

Die Seite gibt immer eine Antwort von 200 zurück, unabhängig davon, ob ein Formularfehler vorliegt oder nicht. Wie kann ich überprüfen, ob mein Formular fehlgeschlagen ist und ob in dem bestimmten Feld ( soemthing) ein Fehler aufgetreten ist?

Mridang Agarwalla
quelle

Antworten:

250

Ich denke, wenn Sie nur das Formular testen möchten, sollten Sie nur das Formular testen und nicht die Ansicht, in der das Formular gerendert wird. Beispiel, um sich ein Bild zu machen:

from django.test import TestCase
from myapp.forms import MyForm

class MyTests(TestCase):
    def test_forms(self):
        form_data = {'something': 'something'}
        form = MyForm(data=form_data)
        self.assertTrue(form.is_valid())
        ... # other tests relating forms, for example checking the form data
Torsten Engelbrecht
quelle
62
+1. Die Idee von Unit- Tests besteht darin, jede Einheit einzeln zu testen.
Daniel Roseman
13
@ Daniel Aber Integrationstests sind viel nützlicher und es ist wahrscheinlicher, dass sie Fehler erkennen.
Wobbily_col
19
@wobbily_col Es dauert auch länger, den tatsächlichen Fehler in einem Integrationstest zu erkennen. In einem Unit-Test ist es offensichtlicher. Ich denke, für eine gute Testabdeckung brauchen Sie trotzdem beide.
Torsten Engelbrecht
11
So überprüfen Sie auf einen bestimmten Formularfehler:self.assertEquals(form.errors['recipient'], [u"That recipient isn't valid"])
Emil Stenström
18
self.assertEqual(form.is_valid(), True)könnte vereinfacht werden:self.assertTrue(form.is_valid())
Adam Taylor
76

https://docs.djangoproject.com/de/stable/topics/testing/tools/#django.test.SimpleTestCase.assertFormError

from django.tests import TestCase

class MyTests(TestCase):
    def test_forms(self):
        response = self.client.post("/my/form/", {'something':'something'})
        self.assertFormError(response, 'form', 'something', 'This field is required.')

Wobei "Formular" der Name der Kontextvariablen für Ihr Formular ist, "etwas" der Feldname und "Dieses Feld ist erforderlich". ist der genaue Text des erwarteten Validierungsfehlers.

Shane
quelle
Dies löst einen AttibuteError für mich aus: AttributeError: 'SafeUnicode'-Objekt hat kein Attribut' Fehler '
sbaechler
Für Anfänger: Erstellen Sie vorher einen Benutzer und verwenden Sie ihn self.client.force_login(self.user)als erste Zeile in der Testmethode.
Sgauri
Ich hatte ein Problem mit diesem Beitrag (), dann stellte ich fest, dass ich ihn als mehrteilig senden musste, wie folgt: response = self.client.post ("/ form-url /", data = {'name': 'test123' , 'category': 1, 'note': 'note123'}, content_type = django.test.client.MULTIPART_CONTENT) Wenn beim Speichern des Formulars keine leere Instanz mehr vorhanden ist, überprüfen Sie die vom Browser gesendeten Anforderungen
Ghaleb Khaled,
17

Die ursprüngliche Antwort von 2011 war

self.assertContains(response, "Invalid message here", 1, 200)

Aber ich sehe jetzt (2018), dass es eine ganze Menge anwendbarer Behauptungen gibt :

  • assertRaisesMessage
  • assertFieldOutput
  • assertFormError
  • assertFormsetError

Treffen Sie Ihre Wahl.

John Mee
quelle
+1 Dies hat bei mir funktioniert, als es sich um einen allgemeinen Formularfehler handelte, der nicht an ein Feld angehängt wird.
Aaron Lelevier