BDD: Адаптация языка Gherkin для русскоязычных проектов в Asp.Net

Я напишу, как можно адаптировать популярный язык написания тестов Gherkin для русскоязычных проектов без использования сторонних библиотек, а также поделюсь своим опытом использования этого подхода.
Статья — не перевод, она от начала и до конца является описанием моей точки зрения. Тем не менее, прийти к ней мне помог блог Стива Сандерсона (Steve Sanderson). Рекомендую прочитать его статьи, помеченные тегом «Testing».

Пролог


TDD-подход в разработке ПО заслуженно завоевал свое место под солнцем. В течение жизни он постепенно переосмыслялся, переходя из разряда методов для поиска багов в разряд методов для описания архитектуры приложения. Следующим шагом, органично дополняющим эволюционировавший TDD является BDD — Behavior Driven Development.

Суть BDD — в описании системы архитектуры приложения в терминах эксперта предметной области, а не программиста, что позволяет ускорить процесс получения обратной связи и убрать традиционные языковые барьеры между создателями ПО и его пользователями.

С помощью BDD тестировать систему (или, как сейчас принято говорить, описывать сценарии взаимодействия) может не только сам программист, пишущий код, но и PM, не разбирающийся в деталях реализации, но хорошо знающий систему с точки зрения пользователя. Для новичков BDD-скрипты — самый простой и натуральный пусть ознакомиться с документацией проекта.

В последнее время BDD применяется чаще в вебе, по большей части из-за того, что его модель сценариев органично вписывается в принцип «запрос-ответ».

Как это выглядит сейчас


Самыми популярнымы инструментами для работы в стиле BDD являются Cucumber для Ruby и SpecFlow для .NET. Оба они используют язык Gherkin. Вот как это выглядит. Разработчик пишет следующий текст:

Scenario: Show logged in user name
Given I am logged in as a user called "Vlad"
When I visit the homepage
Then the page header displays the caption "Здравствуйте, Vlad!"


Для каждого действия он также пишет соответствующие функции:

Given /I am logged in as a user called "(.*)"/ do |name|
create_user(name)
sign_in_as(name)
end

Then /the page header displays the caption "(.*)"/ do |caption|
page_header.should_contain(caption)
end


Таким образом Cucumber или SpecFlow сможет интерпретировать каждый шаг, вычленить с помощью регулярных выражений параметры и запустить соответствующие TestFixtures. В результате мы получаем test-suit, полностью написанный на человеческом языке и понятный каждому участнику проекта.

Для описания сценариев используется шаблон Given/When/Then: Given задают начальные условия, When — операцию, Then — конечный результат. Все сценарии собраны в специальный файл .feature и как несложно догадаться относятся к какой-то определенной фиче проекта.

Чем этот подход плох


Ну во-первых тем, что для его использования нужно устанавливать SpecFlow. Тем более, как я опишу чуть ниже, реальная потребность в таком инструменте отсутсвтует, все можно сделать средствами Visual Studio.

Во-вторых, у SpecFlow есть проблемы с русским языком и чтобы корректно настроить его под кириллицу нужно приложить немало усилий. Тут можно возразить, что, мол, все мы айтишники и понимаем английский и что русский в коде нам ни к чему. Это не так. Русский язык позволяет резко увеличить читаемость сценариев и отказаться от мучительного процесса перевода языка предметной области на английский.

Как это можно сделать по-другому


Очень просто. С некоторых пор Visual Studio позволяет именовать методы класса с использованием русского языка, по сути это все что нам нужно. Пример выше можно написать так:

[TestMethod]
public void Отображение_имени_залогиненного_пользователя()
{
Если_я_залогинен_как("Vlad");
Когда_я_перехожу_на_главную_страницу();
Я_вижу_на_странице_текст("Здравствуйте, Vlad!");
}


Шаблон Given/When/Then трансформируется здесь в Если/Когда/_. По инерции можно было бы переименовать этот шаблон в Если/Когда/Тогда, но написание «Когда я перехожу на главную, я вижу на странице текст „привет“» смотрится намного более органично чем «Когда я перехожу на главную, тогда я вижу на странице текст...». Таким образом, последнее слово «Тогда» я рекомендую просто опускать для улучшения читаемости.

Работает все это крайне просто — каждый тест-класс нужно отнаследовать от базового, в котором определены все необходимые Given/When/Then шаги.

При написании интеграционных тестов я объединяю в тест-классе связанные фичи-регионы, которые в содержат функции-сценарии. Вот как выгладит AccountIntegrationTest:

image

Если вы уже писали интеграционные тесты (к примеру с использованием WatiN) то вы оцените насколько упростится этот процесс. Вот как раньше выглядел мой сценарий отправки сообщения через форму обратной связи:

[TestMethod]
public void Отправка_сообщения_с_заголовком_и_текстом_без_имейла()
{
string caption = U.GetRandomString();
string text = U.GetRandomString();

using (IE ie = new IE())
{
U.Logout(ie);
ie.GoToContacts();
ie.TextField("Caption").Value = caption;
ie.TextField("Text").Value = text;
ClickOnSendMessage(ie);
ie.Text.ShouldContain("Сообщение успешно отправлено");
Div div = U.GetLastUnreadMailMessageText(ie);
div.Text.ShouldContain(text);
}
}


А вот как он выглядит сейчас:

[TestMethod]
public void Отправка_сообщения_с_заголовком_и_текстом_без_имейла()
{
Если_я_не_залогинен();
Если_я_нахожусь_на_странице_обратной_связи();
Когда_я_печатаю_текст_в_поле("Заголовок", "Заголовок для обратной связи");
Когда_я_печатаю_текст_в_поле("Текст", "Сообщение для обратной связи");
Когда_я_кликаю_по_кнопке_с_надписью("Отправить");
Я_вижу_сообщение("Сообщение успешно отправлено");
Админу_приходит_письмо();
В_этом_письме_содержится_текст("Сообщение для обратной связи");
}


В некоторых случаях для выполнения шага ему нужен контекст — результат выполнения предыдущего шага («В_этом_письме_содержится_текст» использует результат работы «Админу_приходит_письмо»). Его также можно спрятать в базовом классе в виде protected object _lastActionResult; и обращаться к нему при необходимости.

Но и это еще не все. Также можно значительно упростить работу с таблицами. Как правило именно они делают из интеграционных тестов мелкодисперсную кашу. Вот пример работы со списком загруженных фото в альбоме (загружаются файлы фото, у которых впоследствии можно редактировать названия и описания):

image

Заключение


Как видим, с помощью самой IDE можно построить мощное средство тестирования и описания вашего веб-проекта с использованием BDD-подхода. Со временем у вас соберется большая коллекция Given/When/Then-шагов в базовом классе, в помощью которых можно будет построить практически любой сценарий на сайте. Дополняйте вашу библиотеку шагов при необходимости, рефакторите ее так же, как вы рефакторите обычные классы и их методы — эти шаги должны говорить с вами на языке доменной логики.
  • +4
  • 17,5k
  • 6
Поделиться публикацией
Похожие публикации
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 6
  • +1
    Gherkin все-таки лучше выглядит, имхо гораздо.
    • 0
      Дело привычки, и я думаю, что программисту на Ruby менять Gherkin на что-то еще нет смысла. Но в .NET он распространен гораздо меньше, плюс если есть CI-сервер, но установка тулзов для поддержки Gherkin'а может вылиться в серьезную головную боль
      • 0
        А можно подробнее про проблемы? У меня пока работает, но вполне вероятно, что я просто чего-то не знаю.
    • 0
      Спасибо, очень интересный метод.
      Вместо слова «тогда» можно использовать слово «то». Тогда звучит вполне органично.
      Объясните пожалуйста, куда вы размещаете имплементацию этих методов? В том же файле с тестами или отдельно? У вас отдельный файл с имплементацией методов для каждого класса с тестами-фичами?
      Ассерты, на сколько я понял, располагаются в методах «тогда...»?
      • 0
        Писать каждый раз «то» мне показалось тоже недостаточно читаемым. Но дело вкуса конечно.

        Все методы (Если_я_не_залогинен и подобные) находятся в базовом классе BaseTest, соответственно все интеграционные тесты наследуются от него. Получается этакий SuperClass с методами на все случаи жизни.

        Ассерты да, располагаются в «тогда»
      • 0
        Уважаемый автор! Не могли бы Вы показать, как эти тесты выглядят у Вас при запуске, какие получаются отчёты?
        Я рассматриваю Ваш приём как запасной вариант, если у меня не получится со SpecFlow работать.

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