Как сквозные приемочные тесты должны разделять большую функцию на сценарии?

В своей статье " Что в рассказе"? Дэн Норт делает ряд отличных моментов. Три, в частности:

  1. Название сценария должно сказать, что отличается

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

  2. Сценарий должен быть описан в терминах событий, событий и результатов.

    Это самый мощный поведенческий сдвиг, который я видел в командах, принимающих BDD. Просто заставляя бизнес-пользователей, аналитиков, тестировщиков и разработчиков принять этот словарь "дано / когда / потом", они обнаруживают, что мир двусмысленности исчезает.

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

  3. История должна быть достаточно маленькой, чтобы соответствовать итерации

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

Теперь предположим, что кто-то пытается описать сквозные приемочные тесты для некоторой функции в стиле мастера (как он рассмотрел выше).

  • Естественно определять "сценарии" тем, как отличается состояние в самом начале использования функции мастера (действительно, это может соответствовать его пунктам № 1 и № 2 выше), но, конечно, неуместно перечислять все пути через мастера (от начала до конца) в полностью сериализованной форме для создания таких независимых сценариев? Мало того, что это приведет к большому количеству сценариев, но каждый из них будет состоять из множества этапов (вопреки пункту № 3 Дэна) - и многие из этих этапов будут дублироваться между сценариями просто для достижения состояния, в котором они расходятся!

    Scenario: Make a successful booking
      Given that I am at the booking form
      When I do A
      Then I see B
      When I do C
      Then I see D
      When I try to book
      Then I see a successful message
    
    Scenario: Attempt to book, no availability
      Given that I am at the booking form
      When I do A
      Then I see B
      When I do C
      Then I see D
      When I try to book
      Then I see no availability
    
  • С другой стороны, было бы более эффективно определить один сценарий для каждого возможного состояния в начале каждой ветви решений в функции мастера - и When "событие" будет просто единственным шагом, который перенесет эту функцию в следующую ветвь принятия решения. Однако разве это не перемещает SUT вниз по стеку, поэтому мы больше не будем определять сквозные приемочные тесты, а скорее что-то более низкого порядка? Более того, гораздо менее естественно следовать и понимать критерии теста - что наверняка побеждает весь смысл BDD?

    Scenario: Do first step
      Given that I am at the booking form
      When I do A
      Then I see B
    
    Scenario: Do second step
      Given that I see B
      When I do C
      Then I see D
    
    Scenario: Make a successful booking
      Given that I see D
      When I try to book
      Then I see a successful message
    
    Scenario: Attempt to book, no availability
      Given that I see D
      When I try to book
      Then I see no availability
    

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

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

Каков наиболее подходящий способ разделения такой функции на сценарии?

2 ответа

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

Если мы думаем таким образом, мы можем полностью устранить проблему, заключив в себе одного волшебника. Например:

Feature: Fill in my tax form

Scenario: Fill in my tax form
  When I fill in my tax form
  Then my tax form should be filled in

Однако это, вероятно, "высокая" абстракция для чего-то столь же сложного, как это. Чтобы добавить больше деталей, вы должны разделить сценарий на части и найти причину для заполнения каждой части. Затем вы используете причину (почему), чтобы написать свои сценарии.

Если мы вернемся к налоговой форме и представим, что она содержит всего три части (для простоты): личность, доход, расходы.

Теперь мы можем написать такие вещи, как:

Feature: Tax indentification
  As someoene who is taxed
  I need to provide proper indentification
  So I pay for my tax and not someone else's

Scenario: Provide indentification
  Given I am filling in my tax form
  When I provide indentification
  Then I should be asked about my income

Мы можем исследовать печальные пути с такими вещами, как

  When I provide insufficient identification
  Then I should be asked for more indentification

и т.п.

Когда мы осуществим это, мы сможем написать

Feature: Tax - provide income details
  ... 

Given I am filling in my tax form
And I have provided indentification
When I provide my income details
Then I should be asked about my expenses

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

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

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

ИМХО покрытие всех путей для каждого возможного состояния слишком детально. BDD помогает командам совместно определять и делать преднамеренные открытия. Поэтому вам следует сосредоточиться на ключевых примерах ( http://gojko.net/2014/05/05/focus-on-key-examples/).

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

Другие вопросы по тегам