morontt.info

Тестирование → Автоматизированное тестирование

Это вторая запись из серии, посвящённой тестам, первая находится тут. В ней будет описан процесс установки и настройки функционального тестирования в Symfony2 с использованием Behat и Mink

Для начала, наверное, стоит рассказать о том, что такое эти Behat и Mink, и с чем их едят. Первое - это библиотека, которая интерпретирует человеко-понятные сценарии и, собственно, выполняет их в виде тестов. Второе - это абстрактная библиотека эмулятора браузера, которая содержит множество готовых определений, используемых Behat-ом при разборе тестовых сценариев, характерных именно для общих задач браузера. Помимо этих специфических определений, Mink предоставляет объектно-ориентированных интерфейс, позволяющий общаться с браузером. Сложно, конечно, описать это в двух словах, нужно самому посмотреть и пощупать :)

Сперва создадим пустой проект или же будем считать, что он уже существует. Я не стал особо заморачивать себе голову и скачал с офсайта Symfony Standard 2.1.7 without vendors. Установкой всех необходимых библиотек будет заниматься composer, а запускается сей процесс (установки) буквально одним взмахом левой пятки.

php composer.phar install

Ну а теперь займёмся настройкой проекта для тестирования. В первую очередь подправим файл composer.json, добавив в него следующие штуки:

{
    //...blah blah blah
    "require-dev": {
        "behat/symfony2-extension": "dev-master",
        "behat/mink-extension": "dev-master",
        "behat/mink-browserkit-driver": "dev-master",
        "behat/mink-goutte-driver": "*",
        "behat/mink-sahi-driver":  "*"
    },
    "config": {
        "bin-dir": "bin"
    },
    "minimum-stability": "dev",
    //...blah blah blah
}

Опишу по порядку то, что было сделано.

  • require-dev - Здесь описываются пакеты, необходимые только для разработки и тестирования, для их закачки необходимо запустить команду install с опцией --dev, иначе эти пакеты скачаны не будут.
  • Будет использоваться Symfony2Extension для интеграции Behat в проект. Там же, по ссылке, можно заглянуть в документацию на счёт behat/mink-extension или bin-dir, например.
  • minimum-stability - данная опция указывает композеру как фильтровать пакеты по стабильности. По умолчанию установлено значение stable, т.е. скачиваться должны только стабильные версии пакетов. Обычно нет никакой необходимости трогать эту опцию, но так уж получилось, что на момент написания этого поста стабильная версия sahi-драйвера реализует не все функции, описанные в DriverInterface, что приводит к фатальной ошибке.

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

php composer.phar install --dev

После инсталляции необходимых библиотек в корневой директории проекта необходимо создать файл behat.yml приблизительно такого содержания:

default:
  formatter:
    name: progress
  extensions:
    Behat\Symfony2Extension\Extension:
      mink_driver: true
    Behat\MinkExtension\Extension:
      base_url: 'http://your-domain.loc/'
      default_session: sahi
      goutte: ~
      sahi:   ~
  • Если убрать секцию formatter, то в консоли будет отображаться информация по прохождению каждого шага тестовых сценариев. Можно, конечно, посмотреть на эти шаги в отдельности, но когда тестов много, то избыток информации начинает мешать, поэтому любоваться будем только полосой прогресса в виде точек :)
  • base_url - здесь указывается URL, по которому робот будет ломится с нашими тестовыми инструкциями.
  • default_session - здесь прописан использующийся по умолчанию драйвер браузера. Это может быть, например, sahi, который устанавливали в прошлой записи, или goutte - эмулятор браузера без графического интерфейса (headless browser), который работает быстрее того-же sahi, только вот javascript ему не по зубам. Более подробная информация находится тут → Different Browsers - Drivers
  • Про настройку тестового окружения как-нибудь в другой раз. Для примера обойдёмся и без него.

Создадим директорию, в которой будут находиться тестовые сценарии и класс FeatureContext. Для этого выполним команду:

sh bin/behat --init @YourBundleName

В указанном бандле создастся директория Features. В файле FeatureContext.php необходимо заменить родительский класс BehatContext на MinkContext, поскольку тестироваться будет веб-приложение.

Создадим в папке Features файл testComment.feature, в котором напишем следующие сценарии. Проверим, для начала, просто стартовую страницу, после чего перейдём по ссылке в определённую запись и оставим там тестовый комментарий, убедившись в том, что комментарий сохранился.

Feature: testComment
  Start page opening

  Scenario: Successfully opening start page
    Given I am on "/"
     Then I should see "Zend-blog-2"

  Scenario: Add comment
    Given I am on "/"
      And I follow "Установка Sahi"
     Then I should see "Адрес электронной почты нигде не отображается"
     When I fill in "Имя:" with "testname"
      And I fill in "E-mail:" with "test@example.org"
      And I fill in "Website:" with "http://example.org"
      And I fill in "Текст комментария:" with "TEST MESSAGE"
      And I press "Добавить комментарий"
     Then I should see "TEST MESSAGE" in the "div#all-comments" element

Запустим тест

sh bin/behat @YourBundleName

В случае успеха увидим что-то вроде изображённого ниже. sahi-драйвер я использовал неспроста, т.к. комментарии добавляются только посредством AJAX, информация же, отправленная простым сабмитом формы попадает прямиком в спамную таблицу БД, о чём добропорядочные человеки, но с вырубленным яваскриптом, предупреждены заранее.

результат прохождения тестов

P.S. Скажу несколько слов ещё относительно тестов в общем. Они нужны! Если сайт не совсем примитивный и содержит некоторое количество связанных друг с другом компонентов, то не так уж и редко возникают ситуации, когда после незначительных изменений в процессе регистрации пользователя ломается, например, отправка писем, связанных с оформлением заказа. Или, например, случайно обнаружить, что уже полгода как sitemap.xml автоматически не обновляется. Конечно, кто-то скажет, что это всё можно и самому проклацать... Но пусть уж этим занимается робот, не знающий усталости и лени, тем более, что тестовых сценариев со временем будет всё больше и больше (если покрывать ими весь функционал веб-приложения). Даже если попадётся ответственный тестировщик, то не факт, что выполняя несколько часов к ряду заданные тесты, он не пропустит того факта, что, допустим, общая сумма заказа не равна сумме стоимостей товара и доставки.

P.P.S. Упомяну так-же, что и автоматизированные тесты не являются панацеей. Во первых, их пишут те же самые люди, подверженные ошибкам. Во вторых - обычный пользователь всегда умудрится произвести на сайте такие действия, о которых разработчик не то, что не догадывался в процессе написания кода и тестов, но и воспроизвести их не сможет длительное время. На предмет таких событий надо поглядывать хоть изредка в логи сервера. Успешное прохождение всех тестов не означает наверняка, что всё с приложением хорошо, но вот отрицательный результат - это уже явное указание на какие-нибудь неполадки.

Полезные ссылки:

g-plus-icon
comments powered by Disqus
Учтите, что комментарии добавляются только при включённом JavaScript в браузере. В ином случае информация хоть и не пропадёт бесследно, но будет отправлена в спам и вряд ли хоть кто-нибудь её увидит.
Хуторная Елена
avatar
Может, хоть муравьев будешь тут время от времени постить? А то и сказать-то нечего )))
Ответить
morontt
avatar
Да, надо будет добавить. Для разнообразия :)
Ответить
Хуторная Елена
avatar
Надо-надо - муравьи все же как-то понятнее )))
Ответить
morontt
avatar
Да нету свежих фотографий с насекомышами :) Так залип в компьютер, что в лес с фотоаппаратом и не выбираюсь.
Ответить
Хуторная Елена
avatar
Вот это плохо, что не выбираешься )))
Ответить
morontt
avatar
Конечно, ничего хорошего в этом нет :)
Ответить
SlowProg
avatar
Отлично! НАЙС! Долгожданное продолжение. Вполне себе ничего, мне понравилось =) Что-нибудь на эту тему еще планируется?
Ответить
morontt
avatar
Спасибо :) Будет что-то ещё, тему тестов в одной-двух записях не раскроешь. Не описаны пользовательские определения, например, и о приведении БД к исходному состоянию тоже ни слова.
Ответить
Светлана
avatar
Впервые на Вашем сайте. Вижу, что что-то полезное для сайтостроения. Обязательно почитаю, разберусь. С первого раза не совсем поняла, что именно мне нужно.
Ответить
morontt
avatar
Приветствую. Для начала стоит разобраться именно с этим, т.е. понять, что нужно :)
Ответить
SlowProg
avatar
Кстати! Всё время хотел спросить... почему не PHPUnit? В чем-то принципиальное отличие от Behat и Mink, что обосновало выбор?
Ответить
morontt
avatar
Это принципиально различное тестирование - юнит тестирует отдельные компоненты (классы, методы). А здесь функциональное тестирование - неважно, что и как внутри, тестируется функционал. Внешнее поведение.
Ответить
SlowProg
avatar
Да да! Это да, я не верно выразился. Я имел в виду, что в Symfony2 интегрирована поддержка PHPUnit по дефолту. Плюс есть класс для функционального тестирования. И всё, в принципе, работает из коробки. Получается довольно мощный (почти) независимый тестовый фреймворк. Почему бы его не использовать? Он чем-то плох? Или я всё таки чего-то не понимаю?
Ответить
morontt
avatar
PHPUnit используется, функциональное тестирование никаким образом не отменяет модульное. Те же консольные команды (которые \Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand) проверяются, например, юнит-тестами.

А Behat/Mink у меня, скорее, исторически получились. Доклады на конференции, да и указание от работодателя, что их используем :) Я не юзал встроенные функциональные тесты из симфони, но беглый обзор по документации показывает, что тамошний краулер просто парсит ответ, а значит, javascript отпадает (т.е. определённую часть функционала просто невозможно проверить).

Естественно, я могу ошибаться по незнанию и недоумию, да хотя бы и потому, что ни разу использовал :)
Ответить
SlowProg
avatar
Да, всё верно. Это я сглупил. Дефолтовые тесты JS не поддерживают. Вот и разобрлись xDDD
Ответить
Максим
avatar
Клевая статья, спасибо! Может быть подскажите как сделать проверку для нескольких сайтов?
Есть сайты A, B, C (одинаковый функционал, но разные языки). Нужно проверить ключевые моменты работы каждого из них.
Реализация через "Примеры" не подходит потому что может добавиться например сайт D и тогда в каждый чек-лист придется добавлять его.
Ответить
morontt
avatar
А что за реализация через "Примеры"? В голову сходу ничего не приходит, кроме как писать отдельные сценарии для проверки отдельных ключевых моментов.
Ответить
17 комментариев Написать что-нибудь
Поля, помеченные asterisk, обязательны для заполнения.
Адрес электронной почты нигде не отображается, необходим только для обратной связи.
Веб-сайт вводите в формате http://example.org, при желании, конечно.