SpecFlow / Cucumber / Gherkin - Использование таблиц в схеме сценария - PullRequest
17 голосов
/ 25 февраля 2011

Надеюсь, я смогу объяснить свою проблему достаточно четко, чтобы другие могли ее понять. Итак, представьте, у меня есть два следующих гипотетических сценария:

Scenario: Filter sweets by king size and nut content
Given I am on the "Sweet/List" Page
When I filter sweets by 
    | Field               | Value  |
    | Filter.KingSize     | True   |
    | Filter.ContainsNuts | False  |
Then I should see :
    | Value            |
    | Yorkie King Size |
    | Mars King Size   |

Scenario: Filter sweets by make
Given I am on the "Sweet/List" Page
When I filter sweets by 
    | Field        | Value  |
    | Filter.Make  | Haribo |
Then I should see :
    | Value   |
    | Starmix |

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

Scenario Outline: Filter Sweets 
Given I am on the <page> Page
When I filter chocolates by 
    | Field    | Value   |
    | <filter> | <value> |
Then I should see :
    | Output   |
    | <output> |
Examples:
    | page       | filter      | value  | output  |
    | Sweet/List | Filter.Make | Haribo | Starmix |

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

Обходной путь может быть что-то вроде:

Then I should see :
    | Output |
    | <x>    |
    | <y>    |
    | <z>    |
    Examples:
    | x | y | z |

Но это не очень динамично .... в надежде на лучшее решение?:)

Ответы [ 2 ]

34 голосов
/ 27 февраля 2011

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

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

"Однако сценарии копирования / вставки для различных тестов фильтров станут повторяющимися и потребуют много кода - чего я бы хотел избежать."

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

На самом деле то, что вы называете «повторяющимися», является одним из преимуществ использования Gherkin и таких инструментов, как Cucumber или SpecFlow.Если вы можете использовать это предложение снова и снова, снова и снова, это означает, что вам не нужно писать тестовый код снова и снова, снова и снова.

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

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

Третий , не думайте, что спецификациипредназначены для идеального освещения для каждого возможного сценария.Сценарии в основном представляют собой снимки состояния, что означает, что есть некоторые функции, которые могут охватывать бесконечно большой набор сценариев, что невозможно.Ну так что ты делаешь?Напишите функции, которые рассказывают историю как можно лучше.Даже пусть история движет развитием.Однако детали, которые не соответствуют вашим спецификациям или другим случаям, лучше оставить на усмотрение TDD, выполненные в дополнение к спецификациям.

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


В любом случае, это только мои мысли, надеюсь, это поможет.

7 голосов
/ 27 февраля 2011

Технически, я думаю, вы могли бы попытаться вызвать шаги из определения шага:

Вызов шагов из определений шагов

Например, я думаю, что вы могли бы переписать

Then I should see :
| Output   |
| <output> |

Это пользовательский шаг, подобный

I should have output that contains <output>

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

Then "I should see #{iterated_value}"

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

| page       | filter                               | value       | output                           |
| Sweet/List | Filter.KingSize, Filter.ContainsNuts | True, False | Yorkie King Size, Mars King Size |

Или, может быть,

| page       |                              filter-value-pairs | output                           |
| Sweet/List | Filter.KingSize:True, Filter.ContainsNuts:False | Yorkie King Size, Mars King Size |

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

...