2010-11-17 2 views
12

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

Мне кажется, что такое же количество кода написано для огурца и rspec, единственное отличие в том, что для огурца вы отделяете тестовую логику от тестовой записи.

+2

JBehave 1.0 пришел первым - первоначально с отдельными механизмами для примеров классов/испытаний и сценарии. Это было время JUnit 3.8 - JUnit 4.4 сделал ненужным классный пример. Дэн Норт (основатель BDD и JBehave) разработал RBehave, затем команда RSpec объединила его, а затем Дэвид Челимски использовал обычный текст, и они разделили его на отдельную библиотеку - я думаю, Aslak Hellesoy привел это. Затем мы переписали JBehave 2.0 на основе Cucumber. Для исторического интереса: http://blog.davidchelimsky.net/2007/10/25/plain-text-stories-part-iii/ – Lunivore

+0

О, и Огурец немного медленнее писать. См. Мой ответ по той причине, почему и проблемы, решаемые инфраструктурой. – Lunivore

ответ

7

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

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

Только для обновления, функция будет содержать следующее:

Поскольку некоторые заинтересованные стороны системы
Я хотел бы осуществлять деятельность
Так что я могу получить некоторую выгоду из этого

Given a precondition 
When I perform an action 
Then something should happen 

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

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

Given a that a database mock is configured with the following data 
| ID | Username | 
| 0 | igor  | 
When call FindAll on User Repository 
Then I get the following user back 
| ID | Username | 
| 0 | igor  | 

Кроме того, как ваш SUT получает меньше (то есть класс), контекст работы не столь важно. Пользовательский репозиторий не заботится о контексте, например. его не интересует, является ли его потребитель обычным пользователем или VIP-пользователем. Простой компонент (который должен быть, после SRP), полностью детерминирован на основе его входных данных.

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

+0

Как насчет повторного использования кода тестирования путем написания определений шагов? Разве это не имеет значения? – inf3rno

+0

я мог себе представить, что-то вроде этого: 'пользователей Feature, сохраняются в хранилище пользователей \t Сценарий поиска пользователей с хранилищем \t \t Учитывая, что хранилище содержит только пользователь игорь \t \t Когда я спрашиваю хранилище, чтобы найти все пользователь \t \t Затем я получаю только пользователя igor назад' - это более абстрактно, но трудно сопоставить эти термины с UserRepository.FindAll и с MockDatabase – inf3rno

1

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

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

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

Испытание огурца = тест-драйв, поместивший его на дорожку для вращения.

+0

Но в этом проблема. Ничто из того, что вы сказали, не относится к rspec, и нет ничего, что огурец не может сделать. Под сценариями огурец представляет собой обычный рубиновый код, который может включать в себя макеты и тестирование на уровне классов. Так почему же не так? – ryeguy

+0

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

+1

Вы по-прежнему не достаточно конкретны. Почему ** точно ** rspec более подходит для этого? Просто потому, что я делаю 2 разных стиля тестирования, не означает, что я должен использовать 2 разных фреймворка. Существует множество разрозненных смехотворных каркасов, которые можно легко использовать изнутри огурца. Как с rspec, так и с огурцом вы пишете описательные имена тестов, так как это отличается? Когда дело доходит до этого, разница в сценариях огурца находится в отдельном файле. Не просто сказать «ну, ничто не останавливает тебя». Я знаю это. Я просто хочу знать, почему все думают так неправильно. – ryeguy

4

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

Он также представляет целый ряд других проблем. Во-первых, вам нужно связать сценарии Cucumber с набором светильников, так что есть еще один слой абстракции, который заставляет их писать медленнее. Во-вторых, английский труднее реорганизовать, чем код, даже с динамическими языками, такими как Ruby (разница еще более выражена в вариантах C# и Java, таких как JBehave, SpecFlow, Cuke4Nuke и Cuke4Duke). Труднее сказать, все еще используются этапы, и сложнее поддерживать сценарии. Сложнее управлять состоянием между различными шагами.

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

Из-за накладных расходов на огурцы, а также потому, что мы не получаем преимуществ от преимуществ, которые Cucumber обеспечивает взамен своих накладных расходов, RSpec лучше подходит для поведения на уровне единицы. (Это также относится к JUnit, NUnit и т. Д.)

Если вам не хватает «Given, When, Then» из огурца, попробуйте добавить их в качестве комментариев. Это хорошо работает для меня.

0

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

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

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

Итог:

модульного теста проверяет, что определенный кусок кода пребывает в его контракте с остальным миром ...

В то время как тест огурца проверяет взаимодействие из несколько фрагментов кода (вертикальный фрагмент, который могут сказать некоторые люди), с дополнительной красотой, которую сам тест читает, как простой английский.

0

Согласно Aslak Hellesøy, Cucumber - это не инструмент для тестирования, а инструмент для совместной работы (для BDD).Недавно он опубликовал об этом очевидном заблуждении:

https://cucumber.pro/blog/2014/03/03/the-worlds-most-misunderstood-collaboration-tool.html

Тем не менее, есть много тестов, написанных ниже уровня приема, который будет падать вокруг испытываемого интеграции слоя. Т.е.,

Given a user at 123 Evergreen Terrace 
When I lookup their name 
Then I get Homer Simpson 

вместо

Given an address 
When I lookup a name 
Then the home owner name is displayed 

Это не помогает, что cukes.info показывает, как императивном примера (а не декларативного).

Тесты на огурцы проходят медленно по сравнению с Rspec или Test :: Unit или MiniTest. У них много накладных расходов (на загрузку среды может потребоваться несколько минут, включая все классы объектов страницы, анализ файлов функций и фактическое выполнение тестов). Выполнение только те же тестов, что и в Cucumber, было бы быстрее, чем запуск интеграционных эквивалентных тестов, но не так быстро, как запуск чего-то более легкого веса, такого как три вышеупомянутых.

(Я отвечаю на этот старый вопрос, так как это был один из первых хитов я получил при поиске альтернатив огурца для тестирования интеграции)

Смежные вопросы