Всем привет!
Сегодня я хочу поделится нашим опытом автоматизации тестирования веб-приложения с использованием Selenium WebDriver и фреймворка Behave.
Если интересно добро пожаловать под кат.

Перед началом


Тут я не буду подробно останавливаться на том, как искать элементы, и как взаимодействовать с ними при помощи selenium webdriver, а расскажу только о том, как можно легко и удобно писать и гонять тесты написанные на python с использованием behave.

1. Установка нужностей


Для начала нам понадобится python. Скачать его можно тут. Я буду использовать версию 2.7.6, а вы можете использовать ту, которая вам больше нравится. Кроме python нам еще понадобятся selenium и сам behave.
Установить selenium можно с использованием pip:
pip install selenium
Что такое selenium?
Как лаконично подсказывает wiki:
Selenium — это инструмент для тестирования Web-приложений.
Так же про него много писали на Хабре:
тут, и тут даже есть частичный перевод не официальной документации

Подробнее про Selenium можно узнать:
официальная документация
перевод
не официальная для selenium with python
официальная для selenium with python


Теперь установим behave. Можно с использованием pip:
pip install behave
А можно скачать тут: behave на pypi
Что такое behave? Behave — это фрейморк для программирования через поведения в python-стиле(Что такое Behavior-driven development?).
Behave использует тесты написанные на натуральном языке, с логикой на python.
Он обладает несколькими серьезными плюсами:

+ Легкая установка
+ Отчеты в формате junit
+ Тесты может писать любой человек на естественном языке.
+ Есть возможность интеграции с jenkins (с другими CI, наверное, тоже)

Сравнение behave с похожими инструментами.
Когда все необходимое установлено можно приступать к настройке окружения для написания и выполнения тестов.

2. Настройка


Директория откуда будем запускать тесты должна содержать:
1. Файлы с расширением .feature — сами тесты.
2. Директорию steps, которая содержит файлы .py с описанием шагов, из которых составляются тесты, на python.

Опционально можно добавить в директорию содержащую папку steps файл — environment.py c кодом который надо будет выполнять прежде или после определенных событий в тесте.
Подробное описание этого файла тут.
Наш пример будет максимально простым, поэтому мы не будем включать этот файл.

Итого, как выглядит наша директория в минимальной комплектации:

features/
features/everything.feature
features/steps/
features/steps/steps.py

пример из behave tutorial
Вот и вся настройка, можно писать первый тест!

3. Написание и запуск первого теста


Для начала нам понадобится создать в папке steps, файл c расширением .py, в котором мы опишем логику нашего теста.
Назовем этот файл first_test.py.
Для примера, я решил взять простой кейс тестирования поисковой формы ya.ru.

Итак, скопируйте код ниже в файл firs_test.py.
# -*- coding: utf-8 -*-
from behave import *
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time

#Откроем главную страницу. Передадим в качестве аргумента адрес страницы.
@given('website "{url}"')
def step(context, url):
#Измените строку, для выполнения теста в другом браузере
    context.browser = webdriver.Firefox()
    context.browser.maximize_window()
    context.browser.get("http://ya.ru")

#Теперь нажмем на кнопку "Найти"
@then("push button with text '{text}'")
def step(context, text):
    WebDriverWait(context.browser, 120).until(
        EC.element_to_be_clickable((By.XPATH, '//button'))
    )
    context.browser.find_element_by_xpath('//button').click()

#Проверим, что мы на странице с результатами поиска, есть некоторый искомый текст
@then("page include text '{text}'")
def step(context, text):
    WebDriverWait(context.browser, 120).until(
        EC.presence_of_element_located((By.XPATH, '//*[contains(text(), "%s")]' % text))
    )
    assert context.browser.find_element_by_xpath('//*[contains(text(), "%s")]' % text)
    context.browser.quit()


Если лень смотреть код, то логика такая:
1. Открыть ya.ru
2. Клацнуть на кнопку «Найти»
3. Проверить, что на странице выдачи есть текст: «Задан пустой поисковый запрос»

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

#Укажем что это за фича
Feature: Checking search
#Укажем имя сценария (в одной фиче может быть несколько)
Scenario: Сheck some text in search results
#И используем наши шаги.
  Given website "ya.ru"
  Then push button with text 'Найти'
  Then page include text 'Задан пустой поисковый запрос'


Шаги из теста, по декораторам свяжутся с python функциями. (Декораторы обозначены знаком @)

Теперь запустим наш тест.
Перейдем в папку, где он лежит, и выполним команду:
behave -i first_test.feature

Флаг -i указывает, что необходимо запустить только файлы подходящие под паттерн поиска.
Если запустить c флагом --junit то получим отчет в формате junit.

Если все прошло хорошо, то отчет будет, примерно, таким:


Feature: Checking search # first_test.feature:1

  Scenario: Send some text in search box and check some text in search results  # ya.feature:2
    Given website "ya.ru"                                                       # steps/test.py:9 0.662s
    Then push button with text 'Найти'                                          # steps/test.py:14 0.242s
    Then page include text 'Задан пустой поисковый запрос'                      # steps/test.py:22 1.009s

1 feature passed, 0 failed, 0 skipped
1 scenario passed, 0 failed, 0 skipped
3 steps passed, 0 failed, 0 skipped, 0 undefined
Took 0m1.913s



Заключение


Здесь я привел только самое основное.
Фичи selenium неисчислимы, да и behave много чего умеет. В том числе, отчеты в формате junit и интеграцию с jenkis.
Спасибо за внимание, и хороших выходных!

Список использованных материалов


Селениум:
habrahabr.ru/post/152653
habrahabr.ru/post/248559
www.seleniumhq.org/docs
selenium2.ru/docs.html
selenium-python.readthedocs.org/index.html
selenium.googlecode.com/svn/trunk/docs/api/py/index.html

Behave:
pythonhosted.org/behave

Python:
pypi.python.org
python.org

UPD: Если что-то в статье не очень хорошо написано, или чего-то не хватает, то можно высказаться в комментариях, или написать в личку мне, и мы вместе улучшим ее.

Комментарии (12)


  1. Dimones
    17.07.2015 19:30

    А можно хоть часть статьи под кат запихнуть? Ибо больно длинно без него


    1. MaximChistov
      17.07.2015 20:15

      мб он по старинке habracut написал, а там тег теперь cut


    1. Pompeius_Magnus Автор
      17.07.2015 20:17
      +1

      Извините, опыта маловато. Написал так сначала <cut> текст </cut> , a надо было просто </cut> .


  1. AndreyNagih
    18.07.2015 11:38
    -1

    Подскажите, пожалуйста, я не совсем понял.
    В стандартной поставке Behave нет вообще никаких шагов, даже таких банальных как открыть URL и кликнуть элемент? Т.е. чтобы начать писать тесты на естественном языке, мы должны сначала сформировать словарь всевозможных шагов?


    1. Pompeius_Magnus Автор
      18.07.2015 12:48

      Да, все правильно.
      Behave только выполняет тесты, a открыть URL и кликнуть — это уже webdriver.


    1. gigimon
      18.07.2015 19:44

      На behave можно писать не только веб тесты


      1. Pompeius_Magnus Автор
        18.07.2015 20:02

        Раз уж на то пошло, то на behave можно писать тесты для чего угодно.
        Никто и не говорил, что это инструмент специализированный для веб.

        В данном случае, тесты написаны на python с использованием selenium.


        1. gigimon
          18.07.2015 20:18

          Я замечательно знаком с behave и BDD в целом (имеется огромный проект функциональных тестов клиент-серверной системы). Но я предпочитаю lettuce


  1. vaha
    18.07.2015 13:13

    А можно хотя бы пару слов непосредственно об опыте использования на проекте? Кто пишет фичи, сложность сценариев (среднее кол-во шагов), частота изменений в продукте и как сильно они затрагивают тесты? Ну и «среднюю температуру» — сколько тестов, как долго используете?


    1. Pompeius_Magnus Автор
      18.07.2015 13:46

      Можно, конечно.
      Мы только начали использовать описанную систему, поэтому тестов не очень много (~100). Помимо того мы используем pict для генерации наборов входных данных, и с помощью самописного python скрипта, на основне шаблона, генерируем много типовых сценариев, с разными данными. Один тест может включать до 60 одинаковых сценариев, с разными данными. (У нас много форм, которые зависят от того, что находится в других формах, или в бд)

      Для того, кто пишет сами тесты сложность стремится к нулю, потому что не приходится описывать никакой логики\программировать, а просто писать юзкейсы: «в этой форме выбери то, затем проверь появился ли текст на странице» и т.п. Сами шаги (взаимодействие с сайтом, и с бд) представляют из себя несложные python-функции, поэтому и тут про сложность нечего сказать. (ненамного сложнее того, что в примере)

      У нас тесты пишут только тестировщики, на данный момент 1 тестировщик. Тесты запускаются вручную, на машине тестировщика, который их пишет. Баги которые ловят тесты регистрируются тем, кто тесты запустил.

      Частота изменений в продукте — десятки (до сотни, наверное) коммитов в день, изменения как логики, так и интерфейса (в части кода, а не вида). На данный момент тесты довольно устойчивы к этим изменениям.

      Конкретные цифры привести сложно, потому что я не отслеживал этого.


  1. SirArhey
    22.07.2015 09:06

    Забавно, суть этого behave в питоне, такая же как у Cucumber в руби. Даже директории и расширения файлов одинаково называются. А не пробовали пользоваться параллельно с этим фреймворком использовать Page Object? Тест был бы изящнее)


    1. Pompeius_Magnus Автор
      22.07.2015 10:48

      Мы любим питон :)
      Page Object — это да, как раз занимаюсь.