В прошлом тексте про ассерты было упущено и недоговорено нечто важное.
В чем состоит различие между given и when и как это связано с ассертами?
Идея, лежащая в основе этого проста — мы хотим ограничить количество ассертов.
Рассмотрим небольшой пример.
Пускай мы передаем в метод некоторый валидный объект, вызываем дополнительный сервис и обогащаем его свойства.
Я не должен писать код вперед теста, поэтому будем считать, это для только для передачи общей картины.
Нас не интересуют вариации validUser'а. Он не нулевой, у него всегда есть id, на то он и valid. Это и есть precondition, т.е. given.
Фактически нам надо рассмотреть два условия — enrichmentService fail и success. Это condition, т.е. when.
Как отличить одно от другого? Given не требует проверки других кейсов, when — требует. Т.е. whenValidUser требует пары whenInvalidUser, а givenValidUser — не требует.
А enrichmentservice==null? Если мы инжектировали зависимость, то можно считать это частью конфигурации и не думать об этом в тестах. Совсем. Есть preconditions, которые не имеет смысла перечислять.
Если метод принимает просто user, количество проверяемых сценариев увеличивается. Given становится when.
Еще вопрос — но ведь, строго говоря, случайно или намеренно метод может испортить нам юзера? Неужели мы не должны проверять его?
Если мы отвечаем — да, должны, нам придется признать, что это может быть большое бремя. У юзера может быть пятьдесят свойств, и проверять их в каждом методе может быть накладно. Есть балк-проверки с помощью библиотек, но тем самым мы теряем важную функцию теста — предписывать желаемую функциональность, а не подбирать грязь за кривой имплементацией.
Это можно сравнить с аэропортовской секьюрити — кто-то проверяет билет, кто-то багаж, кто-то карманы, и проверки не дублируются на каждом шаге. Т.е. ассерты доверяют тому, что будет делать имплементация, и проверяют только то, что предписывают.
Таким образом, правильно построенный precondition сокращает количество сценариев и ассертов. Мы делаем ассерты только на condition.
К сожалению, фреймворки, как Cucumber, особого различия не делают, поскольку сами precondition не проверяют и для них что Given, что When — одно и то же, чисто описательный термин.
В более сложных случаях бывает трудно отличить одно от другого, что само по себе попахивает. Например, много тестов подряд проверяют одно и то же, или часть условий в тестах забыта, или игнорируется как неуместная.
Это хороший повод реструктурировать спецификации и поправить дизайн.
В чем состоит различие между given и when и как это связано с ассертами?
Идея, лежащая в основе этого проста — мы хотим ограничить количество ассертов.
Рассмотрим небольшой пример.
Пускай мы передаем в метод некоторый валидный объект, вызываем дополнительный сервис и обогащаем его свойства.
Я не должен писать код вперед теста, поэтому будем считать, это для только для передачи общей картины.
public User enrichUser(User validUser){
user.setDetails(enrichmentService.getUserDetails(validUser.getId()));
return user;
}
Нас не интересуют вариации validUser'а. Он не нулевой, у него всегда есть id, на то он и valid. Это и есть precondition, т.е. given.
Фактически нам надо рассмотреть два условия — enrichmentService fail и success. Это condition, т.е. when.
Как отличить одно от другого? Given не требует проверки других кейсов, when — требует. Т.е. whenValidUser требует пары whenInvalidUser, а givenValidUser — не требует.
А enrichmentservice==null? Если мы инжектировали зависимость, то можно считать это частью конфигурации и не думать об этом в тестах. Совсем. Есть preconditions, которые не имеет смысла перечислять.
Если метод принимает просто user, количество проверяемых сценариев увеличивается. Given становится when.
Еще вопрос — но ведь, строго говоря, случайно или намеренно метод может испортить нам юзера? Неужели мы не должны проверять его?
Если мы отвечаем — да, должны, нам придется признать, что это может быть большое бремя. У юзера может быть пятьдесят свойств, и проверять их в каждом методе может быть накладно. Есть балк-проверки с помощью библиотек, но тем самым мы теряем важную функцию теста — предписывать желаемую функциональность, а не подбирать грязь за кривой имплементацией.
Это можно сравнить с аэропортовской секьюрити — кто-то проверяет билет, кто-то багаж, кто-то карманы, и проверки не дублируются на каждом шаге. Т.е. ассерты доверяют тому, что будет делать имплементация, и проверяют только то, что предписывают.
Таким образом, правильно построенный precondition сокращает количество сценариев и ассертов. Мы делаем ассерты только на condition.
К сожалению, фреймворки, как Cucumber, особого различия не делают, поскольку сами precondition не проверяют и для них что Given, что When — одно и то же, чисто описательный термин.
В более сложных случаях бывает трудно отличить одно от другого, что само по себе попахивает. Например, много тестов подряд проверяют одно и то же, или часть условий в тестах забыта, или игнорируется как неуместная.
Это хороший повод реструктурировать спецификации и поправить дизайн.
Nichola
Немного сумбурно всё написано:
0. Given-When-Then они однозначно соответствуют сущностям используемым в большинстве классических определений теста (состояние до — действие — состояние после). Идея в этом, а упомянутое ограничение количества ассёртов это скорее следствие (опциональное и связанное с реализацией).
1. Смесь английского, русского и комбинированного в заголовке как бы намекают что дальше легче не будет, но
2. Хочу предупредить других читателей, что им может таки быть интересно проверить работу с invalid user переданным как validUser именованным параметром.
public User enrichUser(User validUser){
user.setDetails(enrichmentService.getUserDetails(validUser.getId()));
return user;
}
rudnevr Автор
Насчет английского вы правы, но однозначной русской терминологии кажется нет, т. е. ей никто особо не пользуется.
А насчёт инвалид юзера, если идти в эту сторону, то придётся проверять и что сервис на самом деле делает, и детали его откуда. И в том ли мы приложении и том ли контексте. Т. е. у паранойи предела нет.
rudnevr Автор
А насчёт given — так я вообще не про теорию, я про то как пользоваться и зачем.