Часто валидирую, переделываю, упрощаю спецификации, потому хочу описать HOW-TO как писать спецификации правильно на основе своего текущего понимания.
Зачем нужны спецификации?
Советую прочитать
"Specification by Example How successful teams deliver the right software" от Гойко Аджича. Для нас это:
- АС тесты
- способ передачи бизнес информации в разработку
- живая документация и способ фиксирования знаний
Как АС тесты и способ донести информацию до разработчика - это оказалось очень мощной техникой. Если вы не пишите спеки и у вас проблемы с качеством, то советую попробовать.
Спецификации мы пишем на Cucumber, потому рассматриваю только
Gherkin формат.
Какие есть требования к спецификациям? Мое основное требование к спецификациям - это их эффективность.
И обычно проблема со стоимостью спеки. Стоимость - это трудозатраты на создание спеки, ее реализацию и поддержку в течение жизни продукта. Чем меньше придется переделывать спеку со временем, тем она дешевле.
Я переделываю чужие спеки не потому, что они не правильные - если разработчик может реализовать данную спеку, то она верна и имеет value. Я переделываю их, чтобы сделать более дешевыми и потому более эффективными.
Спека
"Пользователь авторизуется, заполняет форму, нажимает "Сохранить" и данные формы сохраняются"
возможна и полезна для продукта, но слишком дорога в поддержке. Потому не эффективна. Сейчас мы не пишем спецификации на GUI совсем. Это слишком дорого для нас. Вместо этого мы пишем
- Спеки на логику
- Unit тесты на View и Save
- Smoke GUI тесты
Требования к спецификации
Мое главная требование к спеке:
- она должна покрывать одно небольшое атомарное действие (action).
- Это то знание, что вы хотите зафиксировать для себя, для Заказчика, для продукта. Нет знания - нет спеки.
Основное правило для Gherkin формата. Мы описываем, что система находится в состоянии А, выполняется action, система переходит в состояние В.
Описывается это в Gherkin формате как
- GIVEN - Состояние А
- WHEN - action
- THEN - Состояние В
Состояние А - это набор исходных параметров, которые влияют на action.
Состояние В - это описание результата в виде других параметров.
Action обычно не имеет параметров, это явное описание действия. Такое как - валидация, сохранение, сложение, проверка и тп. Но в ряде случаев для улучшения понимания возможно перенести часть параметров состояния А в WHEN и указать как параметры действия - action(param). Но лучше не надо!
Важно, что action должен быть как можно более атомарным, маленьким по времени. Представим такую спеку:
- GIVEN пришел запрос на поиск данных
- AND система выполнила поиск и сформировала результат
- WHEN система выполняет валидацию результата поиска
- THEN результат содержит только идентификатор записи
Мы правильно выделили в WHEN, что нас интересует только процесс валидации результата поиска. Но информация о том, что пришел запрос и был выполнен поиск
была лишней. Получается, что спека описывает промежуток времени от момента прихода запроса до момента когда мы валидируем результат поиска. Это может быть очень большой промежуток времени. В результате по данной спеке разработчик реализует именно то что описано:
- создаст запрос
- выполнит поиск
- получит результат
- выполнит валидацию результата
- сравнит результат с ожиданием в THEN
При этом пункты 1 и 2 лишние для данной спеки. Эти делают ее дорогой в исполнении и поддержке. Нам это не нужно. Состояние А здесь - это момент когда мы уже всё нашли, у нас уже есть результат. Остальное к спеке не относится. Потому
- GIVEN система сформировала результат поиска на запрос
- WHEN система выполняет валидацию результата поиска
- THEN результат содержит только идентификатор записи
Мета-шаблон спецификации
При разработке спецификация мы со временем вырабатываем шаблоны, практики для сходных случаев. Они нужны аналитикам из PO support team на уровне
Shu. К сожалению это не позволяет корректно действовать в новых, нетипичных ситуация. Потому хочется описать шаблон спецификаций для мета уровне, который можно использовать в большинстве количестве случаев.
Мы хотим описать некоторую логику "Аction", которую можно представить как черный ящик. Для этого логики есть входные параметры "А" и "В", которые влияют на нее. И один выход "result" как результат выполнения логики.
Что важно:
- Результат всегда один, хотя в результате можно быть набор параметров.
- Результат детерминирован. То есть на основе одних и тех же параметров, результат должен быть одинаков. Из-за большого количества примеров эта ошибка это может быть незаметна.
- Удалить всё что не влияет на логику и результат напрямую.
То есть неважно что именно вы описываете. Представьте черный ящик, данные, которые поступают в него, и результат, который из него выходит. И вся сложность именно в том чтобы из всего многообразия бизнес случаев спецификаций найти этот "черный ящик".
И потом разработчики будут вам сильно благодарны. Название данного черного ящика - это тот метод в коде, который должен быть провалидирован. Вы его явно указали для них.
Ниже ряд ошибок, которые встречаются при написании спецификаций:
Логика использование спецификаций как тесты и валидация результата
- GIVEN есть числа <a> и <b>
- WHEN сложение чисел
- THEN результат <c> - <d>
- Examples
- | a | b | c | d |
- | 2 | 3 | 5 | верен |
- | 2 | 3 | 6 | не верен |
- | 2 | 3 | 4 | не верен |
Спецификация - это не тест, это описание поведения системы. Потому более эффективной будет спека.
- GIVEN есть числа "2" и "3"
- WHEN сложение чисел
- THEN результат "5"
Нет смысла валидировать поведение системы - система детерминирована, любой другой результат кроме описанного невозможен.
Много лишней, ненужной информации
- GIVEN Пользователль авторизовался как "user"
- AND открыл форму и заполнил значения "2" и "3"
- WHEN пользователь выполнит отправку форму
- THEN видит результат "5"
Информация про логин и открытие формы никак не влияет на логику - их нужно удалить чтобы упростить спеку и сделать ее более понятно.
Логика поиска
Часто нужно описать логику поиска значений. Для этого используется следующий шаблон:
- GIVEN Есть список значений
- | key | value |
- | 101 | москва |
- | 203 | самара |
- | 307 | тула |
- WHEN выполняется поиск
- THEN результатов поиска являются значения с идентификаторами "101, 203"
Важно
- Следует перечислить все "edge cases" значения и те атрибуты, которые влияют на логику поиска
- Следует явно указать какие значения должны быть найдены
Результатом логики является список значений
Есть 2 варианта (когда вам не достаточно просто указать идентификаторы значений как в примере выше).
Вариант А.
- THEN в списке результатов присутствуют <key> и <value>
- Example:
- | key | value |
- | 101 | москва |
- | 203 | самара |
То есть вы указываете, что вам важно чтобы в списке результатов были следующие значения. Проблема может быть в том, что в списке результатов так же могут быть значения, которые вы не ожидаете там увидеть. И вы об этом не узнаете - спека будет зеленой. Тогда
Вариант В.
- THEN список результатов равен
- | key | value |
- | 101 | москва |
- | 203 | самара |
То есть вы явно указываете полный список результатов и любое лишнее значение в нем будет FAIL.
Предположения
Вы указали спецификацию с примерами, но в общем виде. Разработчик в рамках общения с аналитиком понял о чем спека и дописал в коде свои предположения по тем данным, что отсутствовали в спеке.
Спека зеленая.
Но потом, пройдет время, и все предположения, что разработчик вписал в реализацию, отнимут кучу времени на анализ и нахождение проблем почему система ведет себя не так как было описано в спецификации. Потому в реализации должно быть зафиксировано лишь то, что написано русским языком в тексте спецификации. И если в такой виде спецификация не реализуема, то ее нужно править.
Использование частицы "Не"
Напишите спеку с описанием того что система не делает и отдайте это на разработку. Чаще всегда пустая реализация, то есть 0 строчек кода уже позволяют системе не делать кучу всего, в том числе и то, что указано в спеке.
Переписывайте спеку без частицы "Не".
Удачи!