24 апреля 2009 г.

Test or die!

Сегодня я расскажу вам о тестах. Нет, я не буду рассказывать, почему это важно или зачем это нужно делать. Об этом вы прочтете у других авторов. Я же расскажу вам при помощи чего я тестирую свои Django-проекты и приложения.

Итак, знакомтесь, tddspry - альтернатива стандартному подходу в тестировании Django приложений.

Как мы знаем из документации и практики для тестирования приложения надо:

  • Собственно написать док или юнит-тест. Если это юнит-тест, то разместить его в tests.py или tests/ приложения (при этом надо помнить, что в этом приложении должен присутствовать хотя бы пустой models.py).
  • Выполнить тесты при помощи ./manage.py test app.

Вроде бы ничего сложного или религиозно неправильного нет. Но, я просто не привык к ним. Не привык и точка. Мне намного проще тестировать приложения при помощи python-nose, а вместо стандартного django.test.Сlient использовать twill-овский браузер.

Не буду вдаваться в подробности почему так произошло, но, поверьте, я рад этому до сих пор. Единственное, что меня не устраивало в последнее время это кое-какая монструозность нашей библиотеки для тестирования (которая tddspry и зовется ;) ). И посему я решил вспомнить и применить на практике значение слова рефакторинг. Прошел процесс быстро и практически безболезнено и за три неплоных дня мы имеем практически, да чего уж там таить, фактически новое лицо для нее.

Итак, что-же сейчас умеет tddspry:

  • Есть три базовых тест-кейса:
    • tddspry.NoseTestCase - этот тест-кейс предназначается для любых тестов и по-большому счету является нашим ответом Чемберлену unittest.TestCase. Его особенности: он содержит все декораторы из nose.tools как статические методы класса, а все прочие функции из того же nose.tools как методы объекта.
    • tddspry.django.DatabaseTestCase - этот тест-кейс предназначается для тестов в которых необходимо использовать базу данных. Как и в стандартном поведении unittest.TestCase он создает или просто настраивает для тестов: а) базу данных sqlite3 в оперативной памяти; б) текущую базу данных из settings файла проекта; в) тестовую базу данных. Самым быстрым для тестов является вариант создания sqlite3 базы данных в оперативной памяти и именно он используется по умолчанию. Но никто не говорит, что вы не сможете протестировать любой другой адаптер. Для этого просто укажите database_name аттрибут в вашем тест-кейсе, наследующем DatabaseTestCase. Также, аналогично к джанговским тест-кейсам, DatabaseTestCase умеет загружать фикстуры. И напоследок этот тест-кейс содержит три безумно простых метода для проверки создания, удаления и исправления модели: они же check_create, check_delete, check_update.
    • tddspry.django.HttpTestCase - этот тест-кейс предназначается для тестов серверной части вашего Django проекта при помощи twill-браузера. Почему twill? Потому что он простой и он на Python'e ;) Единственным существенным его недостатком считаю отсутствие простой функции для кастомного (не GET-запроса), посему в тестировании POST или PUT запросов вам прийдется дополнительно использовать или джанговский тест-клиент или просто напросто urllib2. Так, но это мы отвлеклись. Что еще особенного в HttpTestCase? Да то, что он содержит в себе все функции из twill.commands, а также кое-какие стоящие хелперы, как то login, login_to_admin, logout, из названия которых становится ясно, что они делают. Также упрощен интерфейс перехода по урлам, в функцию go можна передать как уже чистый урл, так и только имя его урлпаттерна, которое будет сконвертировано в чистый урл при помощи django.core.urlresolvers.reverse.
  • Есть пару воспомогательных хелперов как-то:
    • tddspry.django.helpers.create_profile
    • tddspry.django.helpers.create_staff
    • tddspry.django.helpers.create_superuser
    • tddspry.django.helpers.create_user
    из названия которых вроде бы опять становится ясно, что они делают.
  • Есть крутой воспомогательный хелпер для проверки работы регистрационного механизма django-registration. Он зовется tddspry.django.helpers.registration.registration.
  • Есть прелесный декоратор show_on_error, который автоматически включен для каждого тестового метода в HttpTestCase. Его прелесть заключается в том, что при ошибке twill'a он показывает содержимое страницы на которой произошла ошибка или при наличии переменной окружения TWILL_ERROR_DIR сохраняет в этой директории html-страницу с ошибкой.

Для установки библиотеки, достаточно просто выполнить sudo easy_install tddspry. А для непосредственного тестирования вашего Джанго-проекта или приложения необходимо присвоить переменной окружения DJANGO_SETTINGS_MODULE значение актуальных настроек и сказать nosetests :)

Для окончательного примера покажу, какой командой тестируется сам tddspry:

PYTHONPATH=/srv/projects/tddspry-github:. DJANGO_SETTINGS_MODULE=testproject.settings nosetests -w .. --with-coverage --cover-package=tddspry --exe testproject

Так что, надеюсь, что моя информация будет вам полезна и вы будете следить за дальнейшим развитием tddspry. Ведь в планах у меня есть поддержка Django 1.1, использование Selenium или Windmill для клиентских тестов и куча прочих полезностей.

зы. Совсем забыл ;) Примеры тестов, написанных при помощи tddspry, вы можете найти где-то здесь.

зыы. Особенная благодарность Almad'у, автору django-sane-testing, за стимул к полному рефакторингу tddspry. Краткое объяснение: он написал мне в личку на гитхабе, мол так и так, я уже сделал практически то же самое только с Селениумом и без Твилла, посмотри может тебе пригодится. Я посмотрел на его тесты и я окончательно понял, что надо улучшать tddspry.

blog comments powered by Disqus