Программное обеспечение (ПО) начинается как идея.
Давайте предположим что есть хорошая идея — идея, которая способна сделать мир лучше, или хотя бы сделать кого-то богаче. Задача разработчика — взять эту идею и преобразовать ее в реальность, во что-то, что действительно приносит пользу.
Первоначальная идея это совершенство, прекрасное. Если кто-то, у кого есть идея к тому же талантливый разработчик программного обеспечения, тогда нам повезло: идея может быть воплощена в рабочий программный продукт даже без надобности объяснять кому бы то ни было. В большинстве случаев, однако, тот, кто владеет оригинальной идеей не имеет необходимых навыков программирования для воплощения её в жизнь. Идея должна быть передана посредством коммуникаций.
Большинство проектов по разработке ПО состоит из команд в несколько совместно работающих людей, поэтому высококачественные коммуникации так важны для их успеха. Как вы наверное уже знаете, хорошая коммуникация это не только красноречивое описание ваших идей своим слушателям, вам так же необходимо просить обратную связь, чтобы быть уверенным, что вы были поняты правильно. Вот почему agile-команды по разработке ПО научились работать маленькими инкрементами, используя программное обеспечение, которое разрабатывают инкрементально, как обратную связь от стейкхолдеров: "Это то, что вы имели в виду?"
Но даже этого недостаточно. Если разработчики тратят двухнедельную итерацию на разработку недопонятых требований, они не только тратят зря свои усилия в течение этих двух недель, но еще и портят целостность кода концепциями и функционалом, которые не отражают оригинальную идею. Другие разработчики уже могли, по неосторожности, начать писать больше кода поверх тех недопонятых требований, уменьшая тем самым вероятность 100%-го исчезновения плохого кода из базы.
Нам нужен фильтр для защиты нашей базы кода от этих недопонятых идей.
Идея автоматических приёмочных тестов (automated acceptance tests) происходит из Экстремального Программирования (eXtreme Programming, XP)1, а именно практики разработки через тестирование (Test-Driven Development, TDD)2.
Вместо того чтобы стейкхолдеры раздавали требования команде разработки без возможности получить обратную связь, разработчики и стейкхолдеры сотрудничают в написании автоматических тестов, которые описывают результат, ожидаемый стейкхолдерами. Мы называем такие тесты приемочными, потому что такие тесты описывают что ПО должно делать, чтобы стейкхолдеры считали его поведение готовым. Тесты падают в процессе написания, потому что исходный код ещё не был написан, но тесты заключают в себе поведение, которое заботит стейкхолдеров и дает каждому четкое понимание, что должно быть сделано, чтобы достичь результата.
Эти тесты отличаются от модульных тестов (unit tests), которые помогают разработчикам создавать и развивать дизайн ПО. Иногда говорят, что модульные тесты нужны для того, чтобы убедиться, что ПО разрабатывается правильно, тогда как приёмочные тесты нужны для того, чтобы убедиться, что вы разрабатываете правильное ПО.
Автоматические приёмочные тесты были устоявшейся практикой среди хороших XP-команд годами, но много менее опытных agile-команд видят TDD как активность исключительно для разработчиков. Как замечают Лиза Криспин и Джанет Грегори в "Agile Testing"3, без насыщения автоматических приёмочных тестов бизнес-фактами программистам сложно догадаться какие unit-тесты им нужно написать. Автоматические приёмочные тесты помогают вашей команде фокусироваться, подтверждая, что работа, которую вы выполняете каждую итерацию, самая ценная работа, которую вы могли бы выполнить. Вы по-прежнему делаете ошибки, но вы будете делать их намного меньше, что означает, что вы можете пойти домой вовремя и наслаждаться жизнью.
Разработка через поведение (Behavior-Driven Development, BDD) ведётся поверх TDD, формализуя хорошие привычки лучших TDD-практиков. Лучшие TDD-практики работают outside-in, начиная с "красных" приёмочных пользовательских тестов, которые описывают поведение системы с точки зрения пользователя. Как BDD-практики, мы понимаем необходимость писать приемочные тесты, как примеры, которые любой из членов команды может прочитать. Мы используем процесс написания таких примеров для получения обратной связи от бизнес-стейкхолдеров, чтобы выяснить, действительно ли мы собираемся разработать правильное решение до начала его разработки. В процессе разработки мы осознанно тратим усилия на разработку коллективного, единого языка (Ubiquitous Language) для общения о системе.
Как описывает в своей книге "Domain Driven Design"4 Эрик Эванс, много проектов по разработке страдают от низкоквалифицированной коммуникации между экспертами предметной области и программистами в команде:
Проект сталкивается с серьезной проблемой, когда его язык имеет трещины. Эксперты предметной области используют свой жаргон, в то время как члены технической команды говорят на своем языке, удобном для общения терминами проектирования… Через это языковое деление эксперты предметной области неопределенно описывают, что они хотят. Разработчики, испытывая трудности осознания предметной области, которая новая для них, смутно понимают её.
С помощью мозгового штурма членами команды может быть рожден единый язык (Ubiquitous Language), который будет применяться и понятен каждому вовлеченному в процесс. Когда команда использует язык последовательно и в общении, и в документациях, и в коде, разногласие при переводе между диалектами каждого будет ликвидировано, и вероятность недопонимания сократится в разы.
Фреймворк Cucumber помогает облегчить обнаружение и использование единого языка с командой, посредством предоставления двум лингвистически отличающимся сторонам место, где они могут встретиться. Cucumber тесты взаимодействуют напрямую с кодом разработчиков, но они написаны в промежуточном слое и на языке, который понятен бизнес-стейкхолдерам. Работая вместе над написанием этих тестов — совместно их определяя — не только члены команды решают, какое следующее поведение нужно разработать, они учатся как описывать это поведение на общем языке, который понятен каждому.
Когда мы пишем эти тесты до начала разработки, мы можем изучить и искоренить множество недопониманий задолго до того, как они проложат свой путь в код.
Что выделяет Cucumber из массы других инструментов TDD? Cucumber был разработан целенаправленно как инструмент, гарантирующий легкое чтение и написание приёмочных тестов любым членом команды. Это показывает истинное значение приемочных тестов: как инструмент для коммуникаций и совместной работы. Простота чтения Cucumber-тестов вовлекает бизнес стейкхолдеров в процесс, тем самым помогая вам действительно исследовать и понимать их требования.
Ниже пример приемочного теста на Cucumber (так же известный, как язык Gherkin):
Feature: Sign up
Sign up should be quick and friendly
Scenario: Successful sign up
New users should get a confirmation email and be greeted personally by the site once signed in.
Given I have chosen to sign up
When I sign up with valid details
Then I should receive a confirmation email
And I should see a personalized greeting message
Scenario: Duplicate email
When someone tries to create an account for email address that already exists.
Given I have chosen to sign up
But I enter an email address that has already registered
Then I should be told that the email is already registered
And I should be offered the option to recover my password
Обратите внимание на то, как в тесте перечисляются примеры в сценариях. Эти сценарии описывают наши ожидания поведения системы. Такое использование примеров оказывает огромный эффект — люди могут визуально представить систему до того, как она будет разработана. Любой из членов команды может прочитать такой тест и сказать, действительно ли тест соответствует их пониманию как система должна работать, и у них так же могут возникнуть идеи новых сценариев, которые можно взять на проработку. Книга Гойко Аджича "Specification by Example" содержит множество случаев, где команды открыли такой подход и применяли его в целях выгоды.
Приемочные тесты, написанные в таком стиле становятся больше, чем просто тесты: они становятся исполняемыми спецификациями.
Бизнес-стейкхолдеры могут читать и писать как спецификации в виде традиционной документации, так и в Cucumber тестах, но у Cucumber тестов есть исключительное преимущество: вы можете запустить их на компьютере в любое время и решить, насколько они точны. На практике это означает, что ваша документация вместо того, чтобы быть созданной единожды и постепенно устаревать, становится живущим сущностью, которая отражает истинное состояние проекта.
Для многих команд тесты становятся источником правды об истинном поведении системы. Имея одно место для хранения подобной информации экономит кучу времени, которое часто тратится впустую, пытаясь синхронизировать документацию, тесты и код. Это так же помогает построить доверие внутри команды, так как у членов команды отпадает нужда в хранении личных версий документов.
Информация взята из книги "The Cucumber Book Second Edition", Matt Waynne, Aslak Hellesoy, with Steve Tooke, 2017.
-
Кент Бек, "Extreme Programming Explained: Embrace Change" (на русском "Экстремальное программирование", 2002 г.).
-
Кент Бек, "Test-Driven Development: By Example" (на русском "Экстремальное программирование. Разработка через тестирование TDD", 2003, 2020 гг.).
-
Лиза Криспин, Джанет Грегори, "Agile Testing: A Practical Guide for Testers and Agile Teams" (на русском "Agile-тестирование: Обучающий курс для всей команды", 2019 г.).
-
Эрик Эванс, "Domain-Driven Design: Tackling Complexity in the Heart of Software" (на русском "Предметно-ориентированное проектирование (DDD). Структуризация сложных программных систем", 2018 г.).
Адаптировала: Тюрина Олеся.
Остались вопросы? Задавай в нашем чате.