Package: m3-wellbehaved
# WellbehavedОбертка вокруг питоновского проекта ```behave``` (который, в свою очередь, является портом ```Cucumber``` из Ruby), позволяющая автоматически прогонять feature-файлы в качестве Django-тестов.## Использование* Установите пакет ```django-wellbehaved``` со стандартного PyPi-сервера "БАРС Груп":```pip install django_wellbehaved -i https://<PyPi_сервер_БАРС_Груп>/simple```* Добавьте его в ```INSTALLED_APPS``` проекта:```INSTALLED_APPS += ('django_wellbehaved',)```* Расположите файлы с описанием поведения (_<имя фичи>.feature_) одним из следующих способов:* одна из списка папок, указанного в настройке ```WELLBEHAVED_SEARCH_DIRECTORIES```;* в одной из подпапок корня проекта (настройка ```PROJECT_ROOT```)* Запустить тестирование можно с помощью обычной команды:```python ./manage.py test django-wellbehaved```## Принцип работыПри запуске тестирования _wellbehaved_ обходит все поддиректории в корне проекта (местоположение _manage.py_) и ищет в нихпапки _features_. Каждая найденная папка будет представлена отдельным набором тестов, в котором каждый файл с расширением_.feature_ будет обернут в класс **DjangoBDDTestCase**.Для каждого модуля с папкой features создается отдельный метод: ```test_имяфайла_feature```.Таким образом, вы можете протестировать единичную функцию системы:+ core|+- features|+ - core_func.featurepython ./manage.py test django_wellbehaved.DjangoBDDTestCase.test_core_func_feature## НастройкиНастройки являются необязательными считываются из ```settings.py``` проекта:1. ```WELLBEHAVED_USE_EXISTING_DB``` - использовать для тестирования существующую базу, используется вместе с```TEST_RUNNER = 'wellbehaved.runner.ExistingDBRunner'```2. ```WELLBEHAVED_INITIAL_FIXTURES``` - список фикстур, который будет загружен каждым тестом. Обычно ииспользуется для занесения общих значений в справочники и по формату аналогичен аттрибуту _fixtures_ в _TestCase_.3. ```WELLBEHAVED_FORMATTER``` - модуль форматирования, используемый _behave_ для вывода результатов. Возможные варианты описаны в [списке модулей форматирования behave][behave Formatters], по умолчанию стоит ```[pretty]```.4. ```WELLBEHAVED_LANG``` - код языка, на котором написано описание функционала. По умолчанию стоит ```'ru'```.## Gherkin(здесь и далее - перевод и легкая адаптация статьи ["Writing Features - Gherkin Language"][Writing Features])**Gherkin** - человеко-читаемый язык для описания поведения системы, который использует отступы для задания структуры документа,(пробелы или символы табуляции). Каждая строчка начинается с одного из ключевых слов и описывает один из шагов.Пример:Функция: Короткое, но исчерпывающее описание требуемого функционалаДля того, чтобы достичь определенных целейВ качестве определенного участника взаимодействия с системойЯ хочу получить определенную пользуСценарий: Какая-то определенная бизнес-ситуацияДано какое-то условиеИ ещё одно условиеКогда предпринимается какое-то действие участникомИ им делается ещё что-тоИ вдобавок он совершил что-то ещёТо получается какой-то проверяемый результатИ что-то ещё случается, что мы можем проверитьОбработчик разбивает файл с тестами на функции, сценарии и входящие в них шаги. Давайте разберемэтот пример:1. Строка **Функция: Короткое, но исчерпывающее описание требуемого функционала** начинает собойописание функционала и дает ему название.2. Следующие три строчки не обрабатываются и не несут никакой смысловой нагрузке для обработчика тестов,но они задают контекст тестирования и одновременно описывают, какую пользу мы получим от этого функционала.3. Строка **Сценарий: Какая-то определенная бизнес-ситуация** начинает сценарий и содержит его описание.4. Следующие 7 строчек описывают шаги теста, каждому из которых впоследствиибудет сопоставлен определенный программный код, выполняющий описанное действие.Сопоставлению подлежат части строк лежащие после ключевых слов "Дано", "И", "Когда" и т.д.### Функции (Feature)Каждая функция описывается в отдельном файле с расширением _.feature_. Первая строчкадолжна начинаться с ключевого слова "Функция:", за которой могут идти три строчки с описанием,размеченные отступами. Каждая функция обычно состоит из списка сценариев.Каждый сценарий состоит из списка *шагов*, каждый из которых должен начинаться с одного из ключевых слов:- Дано- Когда- То- Но- ИШаги _"Но"_ и _"И"_ существуют исключительно для удобства чтения и по своим функциям повторяют ключевое слово,с которого начиналась предыдущая строчка.Вдобавок к сценариям, описание функционала может также содержать _структуры сценариев_ и _предыстории_.### Сценарий (Scenario)Сценарий представляет собой одну из ключевых структур в языке _Gherkin_. Каждый сценарий начинаетсяс ключевого слова **"Сценарий:"**, и может содержать в себе название сценария. Описание функционаламожет содержать в себе один или больше сценариев, и каждый сценарий состоит из одного или более шага.Каждый из следующих сценариев содержит три шага:Сценарий: Вася создает новую записьДано я вошел в систему как ВасяКогда я пытаюсь добавить запись в справочник "Лекарства"То мне должен быть ответ "Ваша запись успешно добавлена."Сценарий: Вася не может добавлять запись в справочник леченийДано я вошел в систему как ВасяКогда я пытаюсь добавить запись в справочник "Виды лечений"То мне должен быть ответ "У вас нет прав доступа!"### Структура сценария (Scenario Outline)Достаточно часто приходится писать множество мелких сценариев, которые различаются буквально паройпеременных. Эти повторения могут быстро надоесть:Сценарий: удалить 5 записей из 12Дано есть 12 записейКогда я удаляю 5 записейТо у меня должно остаться 7 записейСценарий: удалить 5 записей из 20Дано есть 20 записейКогда я удаляю 5 записейТо у меня должно остаться 15 записейСтруктуры сценариев позволяют нам более кратко описывать подобные наборы сценариевс помощью шаблонов:Структура сценария: удаление записейДано есть <было> записейКогда я удаляю <удалено> записейТо у меня должно остаться <остаток> записейПримеры:| было	| удалено | остаток || 12	|    5    |   7     || 20    |    5    |   15    |Шаги указанные в структуре сценария не выполняются напрямую, но используютсядля подстановки в них значений из таблицы примеров. Каждая строчка таблицыбудет обрабатываться как отдельный сценарий с указанными значениями вместозаглушек "было", "удалено" и "стало".### Предыстории (Background)Предыстории позволяют вам добавить определенный контекст ко всем сценариям впределах функции. По сути, предыстория - сценарий без имени, состоящий изшагов. Основное отличие в запуске: предыстория запускается перед каждымсценарием:Функция: поддержка многих справочниковПредыстория:Дано есть пользователь с именем "Вася"И есть справочник "Лекарства"И у пользователя "Вася" есть право на запись в  "Лекарство"И есть справочник "Виды лечений"Сценарий: Вася создает новую записьДано я вошел в систему как ВасяКогда я пытаюсь добавить запись в справочник "Лекарства"То мне должен быть ответ "Ваша запись успешно добавлена."Сценарий: Вася не может добавлять запись в справочник леченийДано я вошел в систему как ВасяКогда я пытаюсь добавить запись в справочник "Виды лечений"То мне должен быть ответ "У вас нет прав доступа!"### ШагиФункции состоят из шагов, также известных как _Данные_, _Действия_ и _Результаты_.#### Данные (Givens)Назначение шагов _Дано_ состоит в **приведение системы в известное состояние**перед тем как пользователь (или внешняя система) начнет взаимодействие с системой(в шагах _Когда_). Также можно рассматривать их как предусловия.Пример: создавать объекты сущностей или настраивать БДДано нет пользователей в базеДано база данных пустаяПример: вход пользователя в систему (исключение к правилу "никаких взаимодействий в шаге Дано")Дано я вошел в систему как "Вася"#### Действия (Whens)Назначение шагов _Когда_ состоит в **описании ключевого действия, совершаемого пользователем**.Пример: взаимодействие со страницейКогда я открыл форму добавления учрежденияКогда я ввел "Институт радости" в поле "Наименование"Когда я выбрал в поле "Тип" значение "Институт"Когда я нажал на кнопку "Сохранить"#### Результаты (Thens)Назначение шагов _То_ состоит в **наблюдении результатов выполнения действий**. Наблюдения должны быть связаны с явной пользой, которая указаны в описании функции. Также необходимо помнить, что должен проверяться _вывод системы_ (отчеты, интерфейс, сообщения), а не что-то глубоко закопанное в систему.#### Предлоги (And, But)Если у вас есть несколько шагов _Дано_, _Когда_, или _То_то вы можете писать так:Сценарий: множественные данныеДано что-то первоеДано что-то второеДано и что-то ещёКогда я открою свои глазаТо я увижу что-тоТо чего-то я не увижу...или можете использовать шаги _И_ и _Но_, превращая свой сценарий в нечто более читаемое:Сценарий: множественные данныеДано что-то первоеИ что-то второеИ и что-то ещёКогда я открою свои глазаТо я увижу что-тоНо чего-то я не увижу#### ТаблицыРегулярные выражения, с помощью которых программисты получаютданные из текстового описания шагов позволяют получать небольшие куски данных из самой строчки. Но бывает и такое, что необходимо передать больший объем данных в один шаг. И здесь нам на помощь придут таблицы:Сценарий:Дано существуют следующие пользователи:| Логин | E-mail        | Пароль || user1 | user1@mail.ru | pass1  || joe   | joe@gmail.com | hey    || heyho | hey@hoe.com   | joe    |## КонтактыС вопросами по доработкам, применению и с сообщениями об ошибках пишите на <borisov@bars-open.ru>## Благодарности* Юле Касимовой (<kasimova@bars-open.ru>) - самоотверженное участие в тестировании продукта;* Сергею Чипиге (<svchipiga@bars-open.ru>) - нахождение багов;* Вадиму Малышеву (<vvmalyshev@bars-open.ru>) - продавливании идеи изучения концепций BDD.## Ссылки- [Writing Features - Gherkin Language][Writing Features]- [Behavior Driven Development (from behave documentation)][Behavior Driven Development]- [List of behave formatters][behave Formatters][Writing Features]: http://docs.behat.org/guides/1.gherkin.html[Behavior Driven Development]: http://pythonhosted.org/behave/philosophy.html[behave Formatters]: http://pythonhosted.org/behave/formatters.html