Тестирование Django приложений с помощью Selenium



    Selenium


    Selenium — это очень удобный (имхо) инструмент для тестирования веб-приложений.

    Тесты создаются с помощью дополнения для Firefox, которое может генерировать код теста на различных языках, в том числе и на Python. Затем эти тесты выполняются специальным сервером, Selenium RC.

    Сам по себе Selenium не привязан ни к языкам ни к фреймворкам, поэтому чтобы интегрировать его в систему тестирования Django-приложений, нужно приложить очень небольшие усилия.

    Для решения задачи интеграции я буду использовать библиотеку Django: Sane Testing. Это библиотека, расширяющая возможности стандартной системы тестирования Django, в том числе и поддержкой тестов Selenium.


    Ставим Django: Sane Testing


    Установка этой библиотеки была бы стандартной, если бы она не тянула за собой Django. Что не есть правильно, если вы пользуетесь транком, как и я.

    Скачиваем актуальный релиз, распаковываем (можно в /tmp), открываем setup.py, находим

    install_requires = ['Django>=1.0_final','nose>=0.10'], <br/>
    либо удаляем, либо комментим часть про Django. После этого ставим:

    sudo python setup.py install



    Ставим Selenium


    Нужно поставить сервер и плагин для Firefox. И то, и другое находится на странице загрузки.

    Для установки плагина достаточно открыть ссылку Selenium IDE, разрешить установку плагина, установить его и перезапустить Firefox. Кроме того, уважаемый bazzzman написал расширение для этого плагина (!), для удобства работы.

    Для установки сервера нужно скачать архив по ссылке Selenium RC, распаковать его куда-нибудь. В получившемся после распаковки каталоге будет несколько подкаталогов. Среди них будет selenium-server-x.y.z, это каталог с сервером. Сам сервер — это файл selenium-server.jar. Вот его куда-нибудь копируем, в удобное место, например в /usr/local/lib, после чего весь распакованный каталог можно потереть, он больше не нужен.

    Для удобного запуска создаём скрипт,

    sudo nano /usr/local/bin/selenium-server

    с таким содержимым:

    #!/bin/bash
    /usr/bin/env java -jar /usr/local/lib/selenium-server.jar

    Задаём ему права на выполнение:

    sudo chmod 755 /usr/local/bin/selenium-server

    Проверим: после выполнения команды /usr/local/bin/selenium-server должно появляться что-то эдакое:

    23:58:17.788 INFO - Java: Sun Microsystems Inc. 14.2-b01
    23:58:17.798 INFO - OS: Linux 2.6.31-14-generic i386
    23:58:17.863 INFO - v1.0.1 [2696], with Core v@VERSION@ [@REVISION@]
    23:58:18.111 INFO - Version Jetty/5.1.x
    23:58:18.113 INFO - Started HttpContext[/selenium-server/driver,/selenium-server/driver]
    23:58:18.114 INFO - Started HttpContext[/selenium-server,/selenium-server]
    23:58:18.114 INFO - Started HttpContext[/,/]
    23:58:18.166 INFO - Started SocketListener on 0.0.0.0:4444
    23:58:18.166 INFO - Started org.mortbay.jetty.Server@fc9944


    если так и есть, значит сервер работает ОК.



    Тестовый проект


    Создаём тестовый проект:

    django-admin.py startproject justtotest

    В проекте будет одно приложение, назовём его habrahabr:

    ./manage.py startapp habrahabr

    Наш тестовый хабр будет состоять из одной модели:

    class Greeting(models.Model):
        text = models.CharField(max_length=200)


    одной формы для ввода приветствия:

    class GreetingForm(forms.ModelForm):
        text = forms.CharField(widget=forms.TextInput(attrs={'size':'40'}),
                               error_messages={'required': 'А текст приветствия ввести ? '})
        class Meta:
            model = Greeting


    и одной вьюшки:

    def Greetings(request):
        template_name = 'habrahabr/index.html'
        title='Selenium'
        if request.method == 'GET':
            form = GreetingForm()
        else:
            form = GreetingForm(request.POST)
            if form.is_valid():
                text = form.cleaned_data['text']
                new_greeting=Greeting(text=text)
                new_greeting.save()
                return HttpResponseRedirect('/')
        greetings = Greeting.objects.all().order_by('-id')
        context = {
                   'title': title,
                   'greetings': greetings,
                   'form': form,
        }
        return render_to_response(template_name, context,
                context_instance=RequestContext(request))


    на которой выводится список добавленных ранее приветствий и форма для добавления нового приветствия.



    Создание теста Selenium


    Запустим проект и в браузере создадим тест с помощью плагина, смотрите на видео (советую смотреть в HQ):



    Как видите, у нас получился код на питоне. Из этого сгенерированного кода возьмём файл класса и немножко доработаем его, чтобы в нашем tests.py получилось вот такое:

    # coding: utf-8
     
    from djangosanetesting.selenium.driver import selenium
    import unittest, time, re
     
    class Untitled(unittest.TestCase):
     
        test_type = «selenium»
        start_live_server = True
     
        def setUp(self):
            self.start_live_server=True
            self.verificationErrors = []
            self.selenium = selenium(«localhost», 4444, "*chrome", «127.0.0.1:8000/»)
            self.selenium.start()
     
        def test_required_text_exists(self):
            sel = self.selenium
            sel.open("/")
            sel.type(«id_text», «Testing with Selenium»)
            sel.click(u"//input[@value='Добавить']")
            sel.wait_for_page_to_load(«30000»)
            try: self.failUnless(sel.is_text_present(«Testing with Selenium»))
            except AssertionError, e: self.verificationErrors.append(str(e))
     
        def tearDown(self):
            self.selenium.stop()
            self.assertEqual([], self.verificationErrors)
     
    if __name__ == "__main__":
        unittest.main()


    В класс мы добавили два атрибута. test_type — указывает на тип теста и start_live_server — он говорит о том, что нужно будет запускать тестовый сервер.

    Кроме того, импорты другие, после установки sane у нас уже всё есть в установленном пакете.



    Скрипты для запуска тестов


    Есть два варианта настроек для запуска тестов. Первый вариант — добавить в settings.py переменную TEST_RUNNER, но в этом случае не получится выбирать индивидуальные типы тестов, например, только юнит-тесты, или только селениум-тесты, а ведь не всегда нужно запускать все.

    Поэтому я выбрал второй вариант — написал скрипты для запуска тестов. Первый скрипт, nose-selenium:

    #!/bin/bash
    DJANGO_SETTINGS_MODULE=«settings» PYTHONPATH=".:.." nosetests --with-django --with-djangoliveserver --with-sanetestselection --select-seleniumtests;

    этот скрипт запустит селениум-тесты с тестовым сервером.

    Второй скрипт, nose-unittests:

    #!/bin/bash
    DJANGO_SETTINGS_MODULE=«settings» PYTHONPATH=".:.." nosetests --with-django --with-sanetestselection --select-unittests;

    этот скрипт запустит юнит-тесты, без тестового сервера.

    Можно сделать необходимые скрипты на все случаи жизни, все типы тестов перечислены в документации. Не забудьте установить права на выполнение скриптов, chmod 755.



    Запуск тестов


    Теперь всё готово для запуска тестов. Необходимо стартануть сервер Selenium, /usr/local/bin/selenium-server, после чего можно запускать тесты с помощью скриптов.

    Я не стал делать скринкаст, но будьте уверены, что всё работает ОК — запускается браузер, контачит с сервером, заполняет форму, проверяет наличие текста, результаты выводятся как обычно.

    Код к статье выложил на яндексе, если файл оттуда исчезнет, пишите в личку.



    Резюме


    На мой взгляд, селениум является хорошим дополнением к системе тестов, т.к. позволяет тестить javascript-насыщенные интерфейсы, что стандартной системе тестов не под силу. Кроме того, сама по себе Django: Sane Testing предлагает дополнительные фичи, о которых я вам советую прочесть в документации.

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



    P.S.


    Windmill не пробовал. Если она проще\лучше\надёжнее, чем Selenium, пожалуйста опишите в комментах или в виде статьи. Линк на статью помещу в начало этой.

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 16

      0
      windmill — теже яйца (форк однако), только не «Firefox only» и написан не на какой-то Java B]
      спасибо, познавательно
        +1
        В файрфоксе создаются тесты, а тестить можно в различных браузерах.
          0
          сыроват виндмил ещё и до селениума ему ещё нужно подтягиваться.
          +2
          Использую Selenium уже год почти, действительно один из самых лучших Open Source инструментов для тестирования.
          Жаль что:
          — xpath в IE работает гораздо (!!!) медленнее чем в FF, в Chrome он просто летает. А потому что проект заточен под IE, приходиться страдать.
          — есть проблема с сертификатами, если тестировать сайт через https, Cybervillans сертификат, который есть в наборе, естественно, не катит.
            0
            Далее:
            — Silverlight абсолютно не протестируешь, есть Silvernium, но там надо выставлять явные ссылки на внутренние переменные, а это не есть хорошо.
            — Ajax можно, но приходиться плясать с бубном.

            Отлично:
            — Гибкий набор функций поиска элементов, xpath рулит
            — Selenium IDE хорошо, Selenium RC — еще лучше

            Недавно обнаружил WebAii для Silverlight, тренируюсь… Написал несколько пробных тестов.
            Выяснилось что элементы из классов, наследованных от Popup class-а, от которого в Silverlight можно делать свои красивые всплывающие окошки ваобче не видать… :( Разработчики в курсе, жду свежую версию…

            Вот так…
              0
              А можно про пляски с бубном с Ajax'ом пару слов?
                0
                Мне стыдно, но я юзаю тулзу скриптующую нажатия последовательности клавиш (т.е. событый от соответствующего устройства) для каждого конкретного случая столкновения с Ajax )
                  0
                  Сответственно валидация теста только через скриншот с экрана. :(
              +1
              я понимаю что может не актуально уже… однако я навигируюсь на элементы с помощью CSS селекторов — работает быстрее чем XPath
                0
                Занятно, надо будет как-нибудь вернуться к старому попробовать.
                Однако, старый проект уже немного в прошлом.

                В данный момент у нас автоматизация уже следующего Silverlight проекта, используем WebAii.
                У нас гремучая смесь:
                ConsoleApp в него подключен GallioRepoorts, он запускает NUnit+log4net, а тот управляет запуском набора тестов. И за ходом работы можно следить через log4console :)
              +1
              Весьма актуальная тема. Как показал печальный опыт текущего проекта юниттесты оказались неэффективны. Разработчики юниттестов не очищают сессии алхимии, в итоге объекты в идентити мапе правильные, а в базе нет, и тому подобное… Наверное задействовано слишком много программистов. Не смотря на то, что проходит море тестов — продукт все равно вечно ломается. Вот решили двигаться в сторону акцептанс тестирования, как раз смотрим на селениум. Спасибо за хорошую вводную.
                0
                Пожалуйста :-)
                –2
                Честно говоря джанго к статье за уши притянут.
                Можно біло просто сказать — тестирование с помощью Selenium.
                  0
                  Чегож я не прочитал эту статью 5-ого числа, тогда бы 6-ого было бы легче и быстрее разобраться :)
                    0
                    А можно как-нить развить тему про тестирование (в частности про selenium)?
                    Всё равно не особо понимаю для чего это затевается — видимо не сталкиваюсь я с задачами, которые этого требуют. Но всё равно интересно :))
                      0
                      Про юнит-тестирование Django оч. хорошо описано в документации, а Selenium тесты специфичны по области применения, так что даже того, что есть в этой статье вполне достаточно, чтобы начать тестировать своё приложение. С дополнительными фичами можно ознакомиться в документации.

                      Именно эта статья написана потому, что я не нашёл информации по настройке Django-Selenium в удобоваримом виде, поэтому и написал. Считайте её быстрым стартом, всё остальное уже зависит от Вас :-)

                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                    Самое читаемое