Доклад “BDD. Яйцо или курица. Тест или код?”

В июне выступил с докладом на внутренней конференции управления разработки — КонфУР. Рассказал историю развития автотестов в нашей команде и немного о технологиях, которые используем. Здесь представлю краткую выжимку из доклада.


Команда, в которой я работаю, занимается заказной разработкой как для внутренних, так и для внешних заказчиков. Пишем на Ruby on Rails, для приёмочных тестов используем связку Cucumber + Capybara + PhantomJS. В остальных тестах используется Rspec.

Cucumber — отличное средство для создания сценариев приёмочных тестов. Если кто-то не знаком с ним, то вот так выглядит пример теста:

Background:    Given I logged in as "Операторов Аркадий"    And I am administrator    And following user exist    | last_name | first_name |    | Тестовый  | Иван       |    And I open certificate bind page
Scenario: when user does not have certificate When I bind certificate to user "Тестовый Иван" Then I should see text "Сертификат привязан пользователю"

Мы разработали несколько продуктов, которые в текущее время поддерживаем.

Несколько разработанных сервисов

Изначальный процесс

На этапе формирования команды все тесты, в частности end-to-end тесты, писали разработчики.

У такого процесса было несколько жирных минусов:

  • 30-40% времени разработчика уходило на тесты;

Мы не могли позволить себе тратить столько времени разработчиков на написание тестов и начали думать, как ускорить процесс разработки. Переложить ответственность за приёмочные тесты на тестировщика — самое очевидное и простое решение. Проблема была лишь в том, что я ни разу до этого не сталкивался с ruby и cucumber. Тем не менее, мы решили попробовать схему, когда за end-to-end тесты отвечает тестировщик, а разработчики прекращают их писать. Договорились, что свободное от тестирования задач время я буду тратить на автотесты, выкладывать их отдельным отдельным пулл-реквестом, а разработчики будут проводить ревью.

Приёмочные тесты пишет тестировщик

Спустя некоторое время проявились минусы такого подхода:

  • потеря контекста разработчиками и тестировщиком — тесты на задачу зачастую создавались уже после того, как она была в основной ветке кода, и часто уже была доступна пользователям;

Но были и плюсы: мы разгрузили разработчиков, а я въехал в автотесты.

Обсудив однажды наш процесс разработки, мы воодушевились идеей, что писать приёмочные тесты параллельно разработке задачи — круто и полезно. И решили постараться сделать процесс таким, чтобы в тестирование задача попадала с уже прошедшими приёмочными тестами. Кроме того, мы решили, что в таких тестах должны остаться только проверки работоспособности бизнес-функциональности приложения. Не надо в приёмочных тестах проверять, виден ли элемент на странице, какое значение находится в инпуте, какого цвета кнопка или отображение всех возможных ошибок на форме. Это должны делать более низкоуровневые тесты.

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

Cucumber удобен тем, что сами сценарии можно писать во время создания тест-плана по задаче. Создаёшь интеллект-карту, выделяешь в ней сценарии, которые нужно автоматизировать, и параллельно в блокноте пишешь эти сценарии на Gherkin.

После этого пушишь сценарии в отдельную ветку и говоришь разработчику: “Смотри, тесты для твоей задачи вот в этой ветке”.

Возникает вопрос, а как же писать вспомогательный код для шагов сценария, если не знаешь, какой id кнопки пропишет разработчик? Ответ прост — пишешь вспомогательный код, а внутри добавляешь пометку для разработчика с текстом. Ему останется лишь немного подпилить тест.

Then(/^I should see "([^"]+?)“ input is invalid$/) do | input |    #FIXME добавить тестовый класс лайтбокса  within(‘#FIXME’) do    step %(I should see “.cc-#{input}” selector input is invalid)  endend

Начали писать тесты параллельно с разработкой

Это привело к тому, что у нас:

  • появился минимально-необходимый набор тестов для проверки работоспособности функциональности, не запуская приложение;

Общие степы

У cucumber удобная система определения шагов сценариев (step definitions). Спустя какое-то время мы заметили, что у наших продуктов есть общие степы, которые мы копируем из одного проекта в другой. Решено было вынести общие степы в шаблонный проект. Из него мы разворачиваем приложение с нуля при разработке нового сервиса. Получилось, что у тестировщика появился большой набор степов, используя которые можно не заглядывать во вспомогательный код степа и не думать, как же это работает.

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

Общие степы для сценариев

В дальнейшем это и вовсе позволило нам создать шаблоны тестов для общей функциональности. Например, во многих продуктах, которые мы делаем, существует фильтрация организаций по ИНН. Шаблон теста для фильтра выглядит так:

Scenario: user filters <something> by inn# Given following organizations exists#   | short_name    | inn            |#   | Ромашка       | 7845881001     |#   | Гладиолус     | 7845881002     |#   | Промакашка    | 784588100300   |When a request is made to ""Then I should see 3 table rowsWhen apply <something> filter "7845881001"Then I should see 1 table rowAnd I should see text "Ромашка" in "<column-name>" column of "1" table rowWhen I apply <something> filter "7845881003"Then I should not see table rowsAnd I should see text "7845881003" in <something> filterWhen I reset the filterThen I should see 3 table rows

Нужно лишь засетапить необходимые тестовые данные. Скорость создания тестов для таких типичных задач увеличилась кратно.

Гайд по тестированию

В wiki создали гайд по тестированию, в котором указывается, что тестируют разные виды тестов, и какие инструменты необходимо использовать.

Тесты на русском

Да :)
Решили поэкспериментировать. Взяли небольшой сервис для внутреннего заказчика и попрбовали написать сценарии приёмочных тестов на русском языке. Изначально казалось, что получится ересь, но в итоге оказалось неплохо:

  • переход на родной язык позволяет не отвлекаться на перевод при чтении сценариев, появляется возможность сосредоточиться на содержимом;

Выводы из доклада

  • Экспериментируйте. Пробуйте новое

Пара интересных книжек:

Антон Рычков

Written by

Тестирую веб-сервисы для предпринимателей kontur.ru

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade