Хочу представить приложение для генерации тестов в Django-проектах: TestRecorder. Это что-то вроде Selenium IDE для тестирования интерфейса, только в результате использования этого инструмента создаются тесты для Django. Вы запускаете тестовый сервер, выполняете необходимые действия в браузере и получаете готовые тесты.
Не стоит обольщаться. Полноценные тесты, конечно, вы не получите, но проверку на 500 - вполне. Созданные тесты можно использовать как основу для полноценных тестов. К тому же, при использовании TestRecorder вам практически ничего не нужно знать о тестировании в Python и Django, чтобы создавать и использовать созданные тесты :)
Рассмотрим использование TestRecorder для создания тестов для нашего djbook.ru.
Как это работает
Идею реализацию (а так же стили и шаблоны) почерпнули у django-debug-toolbar. В проект добавляется middleware, который сохраняет все запросы и ответы. На основе записанных данных, сгенерированных при взаимодействии с сайтом, создаются тесты. При создании тестов используется тестовый сервер Django.
Установка
Устанавливаем django-testrecorder. Можно через pip, но т.к. 100% стабильной версии пока нет, не факт что там будет полная версия :)
pip install django-testrecorder
Можно установить из репозитория:
python setup.py install
Добавляем в настройках:
INSTALLED_APPS += (
'testrecorder',
)
RECORDER_FIXTURES = ['sites.json', 'test.json', 'fixtures.json', 'examples.json', 'news.json']
Параметр RECORDER_FIXTURES содержит фикстуры с тестовыми данными.
Использование
Запускаем тестовый сервер:
$python manage.py recorderserver
И заходим на http://127.0.0.1:8000/. Видим диалоговое окно с предложением ввести имя TestCase класса и метода.
Заполняем и начинаем просто пользоваться сайтом там, как он должен работать. В нашем примере просмотрели парочку новостей, залогинились и оставили комментарий. На панели Requests мы можем увидеть все выполненные запросы и удалить ненужные.
После этого выбираем панель "Get Code" и полученный код копируем в tests.py в одном из наших приложений. Отмечу, что приложение должно содержать models.py, иначе Django не найдет тесты. Теперь запускаем тесты:
$python manage.py test <приложение с нашим tests.py>
Вот так вот выглядят созданные test-recorder тесты:
# -*- coding: utf-8 -*-
from django.test import TestCase
from django.core.urlresolvers import reverse
class ViewsTestCase(TestCase):
fixtures = ["sites.json", "test.json", "fixtures.json", "examples.json", "news.json"]
def test_views(self):
url = reverse("news:news", kwargs={"pk": "52"})
response = self.client.get(url)
self.failUnlessEqual(response.status_code, 200)
url = reverse("news:news", kwargs={"pk": "51"})
response = self.client.get(url)
self.failUnlessEqual(response.status_code, 200)
response = self.client.get(reverse("accounts:login"), {'next': '/news/51/'})
self.failUnlessEqual(response.status_code, 200)
data = {
"username": u"admin",
"password": u"admin"
}
url = reverse("accounts:login")+"?next=%2Fnews%2F51%2F"
response = self.client.post(url, data)
self.assertRedirects(response, reverse("news:news", kwargs={"pk": "51"})+u"?")
url = reverse("news:news", kwargs={"pk": "51"})
response = self.client.get(url)
self.failUnlessEqual(response.status_code, 200)
data = {
"object_pk": u"51",
"content": u"Test",
"content_type": u"41",
"reply_to": u"",
"honeypot": u""
}
response = self.client.post(reverse("comments:post"), data)
self.failUnlessEqual(response.status_code, 200)
data = {
"obj_id": u"51",
"last_comment_id": u"",
"ct": u"41"
}
response = self.client.post(reverse("comments:update_comments"), data)
self.failUnlessEqual(response.status_code, 200)
Дополнительные настройки
Все возможные настройки можно посмотреть в testrecorder.settings.py. Можно указать параметры для авторизации и TestRecorder автоматически вас авторизует и добавит self.client.login() в тесты. В djbook.ru используется ModelBackend для авторизации, поэтому нам необходимы username и password:
RECORDER_AUTH = {
'username': 'admin',
'password': 'admin'
}
В параметре RECORDER_IGNORE можно указать шаблон для фильтрации URL-ов при сохранении, например добавим интерфейс администратора или /js18n/:
RECORDER_IGNORE = ('^/admin.*',)
При загрузке файлов они будут сохранены в RECORDER_FILES_PATH и потом будут использованы для тестирования.