Статьи

WebTest превосходит Django Client для функциональных тестов. Вот почему.

После просмотра великолепного выступления Карла Мейера « Тестирование и Django » я использовал библиотеку Яна Бикинга WebTest для функциональных тестов через django-webtest . Я был очень впечатлен и хотел бы подчеркнуть один из моментов Карла — то, что использование WebTest для функциональных тестов лучше, чем использование клиента Django.

Зачем?

Несколько причин — вот несколько:

  • WebTest позволяет вам моделировать взаимодействие с пользователем гораздо более точно, так как он хорош для разметки. Вместо ручного создания запросов GET и POST вы можете использовать API WebTest для перехода по ссылкам и отправки форм — это то, что на самом деле делают пользователи. В результате ваши тесты точно фиксируют пользовательские истории.
  • В заключение следует сказать, что написание функциональных тестов с помощью WebTest проще и быстрее, чем использование тестового клиента Django. Гораздо проще заполнять формы, которые создают сложные массивы данных POST — это особенно заметно в наборах форм.
  • Объект ответа WebTest поддерживает несколько способов анализа HTML-ответа , что упрощает создание сложных утверждений об ответе.

Смотрите с 29:48 в разговоре Карла для более подробной информации.

Пример функционального теста

Рассмотрим эту историю из функциональной спецификации:


Сотрудник может загрузить CSV для создания новых кредитных ассигнований для клиентов.

Вот WebTest для этого:

from django_webtest import WebTest
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
from django_dynamic_fixture import G

from myproject.credits import api


class TestAnAdmin(WebTest):

    def setUp(self):
        self.staff = G(User, is_staff=True)
        self.customer = G(User, username='10000', is_staff=False)

    def test_can_upload_a_csv_to_create_allocations(self):
        index = self.app.get(reverse('credits-index'), user=staff)

        # Specify the file content to upload and submit the form
        form = index.forms['upload_form']
        # CSV content should be: username, credits, start_date, end_date
        content = "10000,250,2012-01-01,2013-01-01"
        form['file'] = 'credits.csv', content
        form.submit()

        # Check that an allocation has been created
        self.assertEqual(250, api.balance(customer))
        self.assertEqual(1, api.allocations(customer).count())

Как видите, использование WebTest позволяет запечатлеть историю в простом и удобочитаемом тесте. Это основано на реальном функциональном тесте моего текущего проекта. Написание вышеуказанного теста заняло около 2 минут.

Другие полезные библиотеки тестирования

Тестовый пример использует django_dynamic_fixture для создания пользователей, указывая только атрибуты, относящиеся к тесту.

Обратите также внимание на то, что в примере TestCase и метода используется несколько необычное соглашение об именах, потому что я использую django_nose с плагином spec из библиотеки pinocchio . Это приводит к тому, что выходные данные читаются как истории из вашей функциональной спецификации:

$ ./manage.py test tests/functional/eshop/credits_tests.py

nosetests --verbosity 1 tests/functional/eshop/credits_tests.py --with-spec -x -s

An admin
- can upload a csv to create allocations

----------------------------------------------------------------------
Ran 1 tests in 0.269s

Это полезный способ запуска функциональных тестов. Это также подталкивает вас к разделению ваших наборов тестов на более тщательно названные, строго сфокусированные тестовые наборы — вместо того, чтобы объединять разрозненные тесты в один тестовый набор.

Резюме

Используйте WebTest для своих функциональных тестов — вы не пожалеете об этом.