Как мне писать тесты для форм в Django?

110

Я хотел бы имитировать запросы к моим представлениям в Django, когда я пишу тесты. Это в основном для проверки форм. Вот фрагмент простого тестового запроса:

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

Страница всегда возвращает ответ 200 независимо от того, есть ли ошибка формы или нет. Как я могу проверить, что моя форма не удалась и что в конкретном поле ( soemthing) есть ошибка?

Мриданг Агарвалла
источник

Ответы:

250

Я думаю, что если вы просто хотите протестировать форму, вам следует просто протестировать форму, а не представление, в котором она отображается. Пример для понимания:

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
Торстен Энгельбрехт
источник
62
+1. Идея модульных тестов состоит в том, чтобы тестировать каждый модуль отдельно.
Дэниел Роузман
13
@Daniel Но интеграционные тесты гораздо полезнее и с большей вероятностью обнаружат ошибки.
wobbily_col
19
@wobbily_col Также требуется больше времени, чтобы определить, в чем заключается фактическая ошибка в интеграционном тесте. В модульном тесте это более очевидно. Я думаю, что для хорошего тестового покрытия вам в любом случае понадобятся оба.
Торстен Энгельбрехт
11
Вот как вы проверяете конкретную ошибку формы:self.assertEquals(form.errors['recipient'], [u"That recipient isn't valid"])
Эмиль Стенстрём
18
self.assertEqual(form.is_valid(), True)можно было бы упростить:self.assertTrue(form.is_valid())
Адам Тейлор
76

https://docs.djangoproject.com/en/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.')

Где «форма» - это имя переменной контекста для вашей формы, «что-то» - это имя поля, а «Это поле является обязательным». - это точный текст ожидаемой ошибки проверки.

Шейн
источник
Это вызывает у меня AttibuteError: AttributeError: объект «SafeUnicode» не имеет атрибута «ошибки»
sbaechler
для начинающих пользователей: заранее создайте пользователя и используйте его в self.client.force_login(self.user)качестве первой строки в методе тестирования.
sgauri
У меня возникла проблема с этим сообщением (), затем я понял, что мне нужно отправить его как составное, как показано ниже response = self.client.post ("/ form-url /", data = {'name': 'test123' , 'category': 1, 'note': 'note123'}, content_type = django.test.client.MULTIPART_CONTENT) Если какой-либо из них застрял с получением пустого экземпляра при сохранении формы, проверьте запросы, отправленные из браузера
Галеб Халед
17

Исходный ответ 2011 года был

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

Но теперь я вижу (2018 г.), что доступно множество подходящих утверждений :

  • assertRaisesMessage
  • assertFieldOutput
  • assertFormError
  • assertFormsetError

Сделайте ваш выбор.

Джон Ми
источник
+1 Это сработало для меня, когда это была общая ошибка формы, которая не прикреплялась к полю.
Аарон Лелевье 01