- PVSM.RU - https://www.pvsm.ru -
На данный момент самым популярным решением для клиентского тестирования является selenium. Стоит заметить, что вполне заслужено — те возможности, которые предоставляет selenium в связке с webdriver'ом, действительно охватывают почти весь спектр пользовательского взаимодействия с веб-приложениями.
Для небольших проектов замечательно подходит вариант с плагинами для браузеров, функционал которых можно расширить добавлением сторонних компонентов (например, UI-element [1]). Но когда проект становится достаточно большим, а многие его части многократно изменяются и даже полностью перепиливаются, после каждого изменения в структуре страницы или способе подачи данных приходится заменять сразу целые блоки тестов, заглядывая чуть ли не в каждый тест. После такого selenium плагины уже перестают казаться столь удобными. И тут на помощь приходят библиотеки selenium, реализованные для многих языков ассоциируемых с веб-разработкой (документация [2] на официальном сайте)
Предлагаю вам посмотреть на возможности клиентского тестирования (в частности django проектов), которые дает python-selenium в связке с библиотекой lettuce.
Давайте посмотрим на те возможности, которые предоставляют эти компоненты по отдельности:
Python-Selenium
Lettuce
На примере простых тестов регистрации и авторизации я постараюсь продемонстрировать основные аспекты работы с lettuce + selenium.
Постановка задачи
Нужно создать 2 теста, которые будут выполнять следущие действия:
Регистрация:
Авторизация:
Уже из постановки задачи видно, что эти 2 теста выполняют схожие действия, но в разном контексте. Приступим к выполнению задачи.
Выполнение задачи
Добавив lettuce в наш django проект, как это описано в официальной документации [3], и установив все необходимые зависимости (в нашем случае это системные пакеты firefox и питонвские модули lettuce и selenium) можно приступать к написанию тестов.
P.S.: для запуска в режиме headless вам пригодятся xvfb и pyvirtualdisplay
Для работы с lettuce необходимо создать следущие файлы:
От себя могу посоветовать включить в проект файл, содержащий структуру страниц вашего приложения (по аналогии с PageObject, используемым в selenium). Назовем этот файл mapping.py и положим в корень проекта. Данное отделение структуры страниц от тестов снижает потребность в переписывании самих тестов при изменении верстки: достаточно поправить соответствующую страницу в mapping.py. Так же это существенно увеличивает читаемость тестов (дальше это будет наглядно показано).
host_url = 'http://example.com'
site_mapping = {
"registration": {
"url": host_url + "/registration/",
"username": "//input[@id='username']",
"email": "//input[@id='email']",
"password": "//input[@name='password1']",
"verify password": "//input[@name='password2']",
"signup button": "//button[@name='signup']",
"status message": "//div[@id='status']",
},
"authorization": {
"url": host_url + "/login/",
"username": "//input[@id='username']",
"password": "//input[@name='password']",
"login button": "//button[@name='login']",
"status message": "//div[@id='status']",
},
}
P.S.: Я использую xpath, т.к. считаю это самым оптимальным способом поиска элементов
from lettuce import before, after, world
from selenium import webdriver
from mapping import site_mapping
@before.harvest
def setup(server):
# world - переменная, используемая lettuce между всеми стадиями тестов, т.е. хранящая в себе информацию между тестами
world.browser = webdriver.Firefox() # открываем браузер
world.mapping = site_mapping # сохраняем структуру в world
@after.all
def teardown(total):
world.browser.close() # закрываем браузер
Feature: Authorization
Scenario: Registration
Open "registration" page
Fill "username" with "myusername"
Fill "email" with "user@example.com"
Fill "password" with "1234"
Fill "verify password" with "1234"
Click "signup button"
See "Welcome aboard" in "status message"
Scenario: Authorization
Open "authorization" page
Fill "username" with "myusername"
Fill "password" with "1234"
Click "login button"
See "Hello! Again..." in "status message"
Как вы видите, отсутствие информации о расположении элементов сыграло роль на читаемости сценариев. Спасибо mapping.py за это
from lettuce import step, world
@step(r'Open "(.*)" page')
def open_page(step, page):
world.current_page = world.mapping[page] # взять url искомой страницы
world.browser.get(world.current_page['url']) # открыть этот url в браузере
@step(r'Fill "(.*)" with "(.*)"')
def fill_element_with_text(step, element, value):
elem = world.browser.find_element_by_xpath(world.current_page[element])
elem.send_keys(value)
@step(r'Click "(.*)"')
def i_click_xpath(step, element):
elem = world.browser.find_element_by_xpath(world.current_page[element])
elem.click()
@step(r'See "(.*)" in "(.*)"')
def i_see_text_in_element(step, text, element):
elem = world.browser.find_element_by_xpath(world.current_page[element])
assert elem.text == text
Вот и все. Осталось только запустить тесты и смотреть, как они успешно (или не очень) проходят.
Кажется, что слишком много телодвижений для написания каких-то двух тестов — так и есть. Но если вы хотите покрыть проект большим количеством тестов, то по мере написания сценариев и шагов к ним, вам все меньше будет необходимо писать новые шаги, т.к. почти все возможное взаимодействие пользователя с вашим сайтом уже будет описано в существующих шагах — останется только писать новые сценарии, что не сложнее, чем было написать пункт «постановка задачи» чуть выше.
Что имеем в остатке:
P.S.: Надеюсь, что кто-нибудь заинтересуется этой темой и будет резонно написать про подводные камни, с которыми я столкнулся, используя lettuce + selenium. Буду рад ответить на ваши вопросы.
P.P.S: Заранее извиняюсь за стиль изложения, пунктуацию и вообще. Первая статья и все такое…
Автор: PukeCloud
Источник [6]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/40719
Ссылки в тексте:
[1] UI-element: http://ttwhy.org/code/ui-doc.html
[2] документация: http://docs.seleniumhq.org/docs/
[3] официальной документации: http://lettuce.it/
[4] хорошая документация по python-selenium: http://selenium-python.readthedocs.org/en/latest/
[5] немного устаревшая, но годная статья по lettuce + splinter: http://cilliano.com/blog/2011/02/07/django-bdd-with-lettuce-and-splinter/
[6] Источник: http://habrahabr.ru/post/189778/
Нажмите здесь для печати.