Изучите передовые методы создания устойчивых веб-приложений с помощью разработки, основанной на поведении.

« Почему мы падаем, сэр? Чтобы мы могли научиться брать себя в руки.
- Альфред (Майкл Кейн) в" Бэтмен: Начало "

Десять лет назад я создал свое первое приложение на Rails. Я перепробовал все подходы, и если в одном я уверен, так это в том, что я не могу работать без написания тестов. И написание тестов в первую очередь - это то, что больше всего помогло мне развить мои навыки программирования.

Все очень просто. Мы хотим чувствовать себя и быть такими же продуктивными в 1000-й день, как и в первый день проекта. Мы хотим быть быстрыми. Для этого нам нужен чистый код.

Мы не можем сделать все правильно с первого прохода, поэтому нам нужно провести рефакторинг. Однако мы не можем проводить рефакторинг из-за постоянного опасения, что мы сломаем что-то и отправим ошибки в производственную среду, не зная об этом. Нам нужна уверенность в том, что, взломав код, мы сможем сразу обнаружить и исправить проблему.

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

Итак, если тесты являются основой, давайте сначала напишем их. Сделайте это какое-то время, и вы заметите, насколько чистым и эффективным будет ваш код и тесты.

Понимание точки зрения «поведения»

При применении разработки через тестирование (TDD) разработчики могут легко попасть в ловушку использования модульных тестов для проверки того, что такое объект или метод, а не то, что он делает, что намного полезнее.

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

Изменение реализации объекта не должно нарушать его набор тестов, пока то, что делает объект, остается неизменным.

Разработка, основанная на поведении (BDD), делает акцент на поведении - на том, что делает объект - на всех уровнях развития.

Поначалу слово «поведение» может показаться странным. Другой способ сформулировать это - подумать об описаниях. Мы можем описать каждый низкоуровневый метод, объект, кнопку или экран другому человеку - и то, что мы будем описывать, является именно тем, что такое поведение. Принятие этого подхода меняет наш подход к написанию кода.

Коммуникационная модель «Дано / Когда / Тогда»

Большинство проблем в разработке программного обеспечения - это проблемы со связью. Например, менеджер по продукту не может описать все варианты использования предлагаемой функциональности. Разработчики неправильно понимают объем функции. У продуктовой команды нет протокола, чтобы проверить, реализована ли функция.

BDD упрощает язык, который мы используем для описания сценариев, в которых следует использовать программное обеспечение:

* Учитывая * некоторый контекст или состояние мира,

* Когда * что-то происходит,

* Тогда * мы ожидаем какого-то результата.

Дано, Когда, Тогда - это простые слова, которые мы можем использовать для описания сложной функции, объекта кода или отдельного метода. Это шаблон, который могут понять все члены команды, выполняющие различные роли.

Эти выражения также встроены во многие среды тестирования, такие как Cucumber. Четкая формулировка проблемы и решение, которое нам нужно реализовать, помогают нам писать лучший код.

Обзор инструментов BDD для Rails

Ruby on Rails был первым веб-фреймворком, который поставлялся с интегрированным фреймворком для тестирования. Это послужило трамплином для дальнейшего развития ремесла.

В то же время выразительность Ruby и повышение производительности при разработке веб-приложений с помощью Rails с самого начала привлекли в сообщество многих опытных и высокопрофессиональных инженеров.

Когда вы создаете новое приложение Rails с параметрами по умолчанию, оно устанавливает сцену для тестирования с использованием test/unit, библиотеки тестирования, поставляемой с Ruby. Однако есть инструменты, которые упрощают применение BDD. Я рекомендую использовать RSpec в качестве основной библиотеки тестирования и Cucumber для написания приемочных тестов высокого уровня.

RSpec

RSpec - популярная библиотека тестирования BDD для Ruby. Тесты, написанные с использованием RSpec, называемые спецификациями, представляют собой исполняемые примеры ожидаемого поведения фрагмента кода в заданном контексте. Это намного легче понять, прочитав следующий код:

describe ShoppingCart do
  context "when first created" do
    it "is empty" do
      shopping_cart = ShoppingCart.new
      expect(shopping_cart).to be_empty
    end
  end
end

Хорошо написанные спецификации легко читать и, как следствие, понимать. Попробуйте прочитать вслух приведенный выше фрагмент кода. Мы описываем корзину покупок, говоря, что, учитывая пустой контекст, когда мы создаем новую корзину, мы expect(shopping_cart).to be_empty.

Выполнение этой спецификации дает результат, напоминающий спецификацию:

ShoppingCart
  when first created
    is empty

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

Огурец

Как я объяснил в первой главе этого руководства, мы хотим протестировать этап анализа каждой новой функции. Для этого нам нужны приемочные испытания клиентов, чтобы стимулировать разработку кода, который фактически реализует эту функцию.

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

Cucumber читает текстовые описания функций приложения, организованные по сценариям. Каждый шаг в сценарии реализуется с использованием конкретного кода и автоматизирует взаимодействие с вашим приложением с точки зрения пользователя. Например:

Feature: Reading articles
Scenario: Commenting on an article
  Given I am logged in
  And I am reading an article with "2" comments
  When I reply to the last comment
  Then the article should have "3" comments
  And I should be subscribed to follow-up comments

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

Цикл BDD в Rails

На практике BDD подразумевает подход снаружи внутрь. Мы начинаем с приемочного теста, затем пишем код в представлениях и переходим к моделям. Такой подход помогает нам обнаруживать любые новые объекты или переменные, которые могут нам понадобиться для эффективной реализации нашей функции на раннем этапе, и принимать на их основе правильные проектные решения.

Цикл BDD в Rails состоит из следующих шагов:

  1. Начните с нового сценария с огурцом. Прежде чем писать, обязательно проанализируйте и поймите проблему. На этом этапе вам нужно знать, как пользовательский интерфейс позволяет пользователю выполнять работу. Не беспокойтесь о реализации этапов сценария.
  2. Запустите сценарий и посмотрите, как он потерпит неудачу. Это сообщит вам, какие шаги не выполняются или ожидают реализации. Сначала большинство ваших шагов будут отложены (не определены).
  3. Напишите определение первой невыполненной или ожидающей рассмотрения спецификации. Запустите сценарий и посмотрите, как он потерпит неудачу.
  4. Протестируйте реализацию представления Rails, используя цикл рефакторинга красный-зеленый с RSpec. Вы обнаружите переменные экземпляра, контроллеры и действия контроллеров, которые потребуются представлению для выполнения своей работы. Это также единственный этап, который на практике оказался необязательным. Альтернативный подход - просто подготовить представления и контроллеры перед переходом к следующему шагу.
  5. Протестируйте контроллер, используя цикл рефакторинга красный-зеленый с RSpec. Убедитесь, что переменные экземпляра назначены и действия реагируют правильно. Контроллеры обычно используют насмешливый подход. Позаботившись о контроллере, вы будете знать, что должны делать модели или объекты вашей области.
  6. Протестируйте объекты домена, используя тот же цикл рефакторинга красный-зеленый с RSpec. Убедитесь, что они предоставляют методы, необходимые для контроллера и представления. Если вы работаете над новой функцией, для которой модель еще не существует, теперь вы должны сгенерировать модель и соответствующие миграции базы данных. На этом этапе вы будете точно знать, что вам нужно от них.
  7. После реализации всех необходимых объектов и методов и прохождения соответствующих спецификаций, запустите сценарий Cucumber, с которого вы начали, чтобы убедиться, что шаг удовлетворен.

После того, как первый шаг сценария пройдет, перейдите к следующему и выполните те же действия. После того, как весь ваш сценарий будет реализован - сценарий будет пройден вместе со всеми базовыми спецификациями - найдите время, чтобы подумать, есть ли что-то, что вы можете реорганизовать в дальнейшем.

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

Этот пост адаптирован из Rails Testing Handbook, бесплатной электронной книги, изданной Semaphore. Если вы зашли так далеко и хотите увидеть несколько практических примеров написания кода, управляемого поведением, скачайте книгу и дайте мне знать, что вы о ней думаете. Спасибо!