В прошлом тексте про ассерты было упущено и недоговорено нечто важное.
В чем состоит различие между 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 — одно и то же, чисто описательный термин.
В более сложных случаях бывает трудно отличить одно от другого, что само по себе попахивает. Например, много тестов подряд проверяют одно и то же, или часть условий в тестах забыта, или игнорируется как неуместная.
Это хороший повод реструктурировать спецификации и поправить дизайн.