Тестирование веб-приложений при помощи mechanize

    По следам хабратопика о Watir, автоматизированном иструменте тестирования для web приложений на языке Ruby, решил написать небольшую статью о подобном инструменте для языка Python. Речь пойдет о замечательной библиотеке mechanize. В отличие от Watir, mechanize не заточен под какую-либ о ОС, и является надстройкой над питоновскими библиотеками urllib и urllib2.

    Сама библиотека является эмулятором браузера (без поддержки яваскрипта) и позволяет решать задачи любого класса (с огладкой на «отключенный» яваскрипт), в которых необходим применение браузера. В частности, я впервые вышел на эту библиотеку, когда нужно было скачать огромное количество научных статей с одного хранилища, требующего авторизации и хранящего документы PDF так, что без помощи вспомогательных инструментов скачивать приходилось исключительно по одному документу, чем я и занимался 2 часа, пока не вспомнил о PERL'овой библиотеке WWW::Mechanize (о возможностях которой читал некоторое время назад) и не набрал в гугле запрос WWW::Mechanize python, который и привел меня на сорсфорж.

    Но довольно лирики.

    Начинается все с установки библиотеки. Подробно прочитать об этом лучше всего на оффсайте в разделе скачивания. Если кратко, то есть 3 основных пути получения этой библиотеки:


    Лично я для себя выбрал третий путь, подробно описывать который в данной статье не имеет смысла, ибо написать лучше и подробнее, чем это сделано на оффсайте у меня все равно не получится.

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

    1. # -*- coding: utf-8 -*-
    2.  
    3. import re
    4. from mechanize import Browser
    5.  
    6. # определим все, что нам может пригодится дальше
    7. root_url = 'http://habrahabr.ru/'
    8. login_url = 'http://habrahabr.ru/login/'
    9. username = 'krig'
    10. userpass = '******'
    11.  
    12. comments_re = r'habrahabr\.ru/blog.*/#comments'
    13. count_re = re.compile('(\d+)\s*\+(\d+)')
    14. post_id_re = re.compile('habrahabr\.ru/blog.*/(\d+)/#comments')
    15.  
    16. def is_logged_in(page_text):
    17.     return not login_url in page_text
    18.  
    19. br = Browser()
    20.  
    21. home_page = br.open(root_url)
    22. print 'Добро пожаловать на', br.title()
    23.  
    24. # проверим залогинены ли мы и попробуем это сделать, если еще нет
    25. if not is_logged_in(home_page.read()):
    26.     print "Пробуем залогиниться"
    27.     br.follow_link(text='войти')
    28.     br.select_form(name="login")
    29.     br["login"] = username
    30.     br["password"] = userpass
    31.     result_page = br.submit()
    32.     if not is_logged_in(result_page.read()):
    33.         print "Не удалось залогиниться"
    34.         exit(1)
    35.     else:
    36.         print "Успешно вошли как", username
    37.  
    38. # посчитаем самое большое количество комментариев на главной странице
    39. max = zero_comments = 0
    40. title = url = ''
    41. print "Начинаем перебор статей на главной"
    42. br.open(root_url)
    43. # при входе на страницу сохраняем все нужные ссылки в список, чтобы не потерять его
    44. # иначе, если в нутри цикла мы перейдем на другую страницу, то br.links(...) будет возвращать
    45. # ссылки с новой страницы
    46. for comments_url in [url for url in br.links(url_regex=comments_re)]:
    47.     m = count_re.search(comments_url.text)
    48.     # если хабракаментов нет, то и совпадений нет
    49.     if not m:
    50.         zero_comments += 1
    51.     else:
    52.         if int(m.group(1)) > max:
    53.             max = int(m.group(1))
    54.             habrapost_id = post_id_re.search(comments_url.absolute_url).group(1)
    55.             post_url = [url for url in
    56.                     br.links(url_regex=r'habrahabr\.ru/blog.*/' + habrapost_id + '/?$')][0]
    57.             title = post_url.text
    58.             url = post_url.absolute_url
    59.  
    60. print 'Хабратопиков без хабракаментов:', zero_comments
    61. print 'Максимальное количество хабракаментов:', max
    62. if max:
    63.     print 'Самый коммментируемый топик:', title
    64.     print 'А находится он по адресу:', url

    Исходный код

    Запускаем скрипт и получаем на выходе что-то вроде:
    $ python habratest.py 
    Добро пожаловать на Хабрахабр
    Пробуем залогиниться
    Успешно вошли как krig
    Начинаем перебор статей на главной
    Хабратопиков без хабракаментов: 0
    Максимальное количество хабракаментов: 72
    Самый коммментируемый топик: Бесплатные компьютеры
    А находится он по адресу: http://habrahabr.ru/blogs/startup_ideas/52540/


    Другие, не менее интересные возможности этой замечательной библитеки вы можете посмотреть на ее оффсайте.
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

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

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

      0
      интересно посмотреть на «позволяет решать задачи любого класса, в которых необходим применение браузера». В качестве примера можно взять ну какой-нибудь аякс-ориентированный сайт, вроде gmail.
        +2
        Прошу прощения, при редактировании пропала оговорка о поддержке яваскрипта. Поправил.
        А под задачами я подразумевал кравлинг, постинг, скачивание и т.п.
        +1
        мага крутая штука. Спасибо за статью
          +3
          А twill вы не пробовали?
            0
            Не пробовал. Обязательно посмотрю, но судя по описанию это просто специализированный скриптовый язык, в основе которого как раз и лежит механайз.
              0
              Это более подходящая для тестирования утилита.
              Mechanize — библиотека, которая подойдет для написания какого-то простого робота.
              А если тестирование сводиться к «зайти по урлу-заполнить форму-проверить код ответа-найти контрольные сообщения», то twill несомненно лучше.
                0
                Twill — это надстройка над mechanize:)
                Его можно использовать как независимый скриптовый язык, а можно подключить как модуль к питоновскому приложению и вызывать функции при помощи питоновского синтаксиса. Для тестирования — супер вещь.
                  0
                  Когда-то решал те же задачи. Но к сожалению остановился на httplib2, оно хоть более низкоуровневое но на тот момент нормально с кешированием по ETag не работало, а мне нужно было чтобы даже несколько тыс клиентов на положили сервер на колени запросами к биллингу.
              +1
              Watir и mechanize немного разные вещи.
              Аналог Watir для python это P.A.M.I.E. (http://pamie.sourceforge.net/)
                0
                Приятная штука, хотя возможности парсера слабоваты. Надо будет попробовать в связке с BeautifulSoup
                  +1
                  BeautifulSoup идет в комплекте =)
                  $ ls mechanize-0.1.11/mechanize | grep be
                  _beautifulsoup.py
                    0
                    Great! Суп это наше всё :)
                  +1
                  Безусловно подобные библиотеки облегчают жизнь, но они всё таки не дают 100% контроля над запросами.
                  Для «глубокого» тестирования я предпочитаю libwhisker, на нём кстати основан известный сканер безопасности Nikto, который как раз предназначен для тестирования веб-приложений.
                  Кстати есть не большая статья по использованию этой библиотеки Using Libwhisker, правда ужасно устаревшая, но у libwhisker есть прекрасная документация, которая поставляется с ним же в архиве.
                  Удачи :)
                    0
                    Мне mechanize не подошел в связи с AJXO'м. Я использую анализатор трафика и свой эмулятор Firefox
                      0
                      во-первых, как уже писали выше — watir и machanize ну совсем разные штуки.
                      во-вторых, если уж тестить клиент, то со всеми потрахами и во всех браузерах. Например, selenium (если честно не знаю проекта более навороченного). В селениуме правда изза горы функицонала и настройка его — не для слабонервных. Зато в результате я смог запустить его вообще везде. И на maxthon под виндой, и в konqueror 3/4 и в опере и в гуглхроме. Короче во всех браузерах без исключения =). Никаких ограничений на используемые технологии нет. Если пользователь может ткнуть по чему-либо, то и selenium сможет.

                      Вместо регулярок надо достаточно хорошо знать xpath.
                        0
                        В офисе селениум установлен на сервере и мы его постепенно внедряем.
                        0
                        Вам, возможно, стоит присмотреться к решениям типа вышеупомянутого Selenium. Существуют плагины (например, под Рельсы), которые позволяют писать скрипты к нему прямо на руби, тестируя сразу все, включая AJAX/Javascript-части вашего приложения.

                        По задумке, вы запускаете Selenium-тесты также как юнит тесты (из того же интерфейса) и тестируете сразу под всеми доступными на вашей платформе браузерами.
                        Оно загрузит fixtures, создаст *_test базу и прогонит тесты через все браузеры. Селениум их сам запустит, потыкает, и вам сразу покажет какое всплывающее окошко где отвалилось, или где забыли показать незаполненное поле.

                        Возможно это решение вам (как и мне в свое время) поможет избежать написания большинства юнит тестов.
                          0
                          Ещё над mechanize и ClientForm сделан пакет zope.testbrowser — тоже рекомендую ознакомиться. Он добавляет разные удобности, вроде красивой работы с формами, reload, goBack, поддержку куки и др. Особенно хорош для автоматических тестов.

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

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