Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Паттерн Given-When-Then
Given-When-Then — это популярный паттерн структурирования тестов (BDD — Behavior-Driven Development), который делает тесты более читаемыми и близкими к бизнес-требованиям. Этот паттерн помогает разработчикам и тестировщикам лучше понимать тестовый сценарий, описывая его на естественном языке.
Основные компоненты
Given (Дано)
Given определяет начальное состояние или предусловия перед выполнением теста. Это могут быть:
- Инициализация объектов
- Установка начальных значений
- Подготовка тестовых данных
- Конфигурация окружения
When (Когда)
When описывает действие или событие, которое должно произойти. Это:
- Вызов метода
- Выполнение операции
- Запрос к API
- Взаимодействие пользователя
Then (То)
Then проверяет результат выполнения действия. Это:
- Утверждения (assertions)
- Проверка вспомогательных эффектов
- Верификация возвращаемых значений
- Проверка состояния объектов
Пример без Given-When-Then
@Test
public void testCalculator() {
Calculator calc = new Calculator();
int result = calc.add(2, 3);
assertEquals(5, result);
}
Этот тест непонятен — неясно, что мы проверяем и почему.
Пример с Given-When-Then
@Test
public void shouldReturnSumWhenAddingTwoPositiveNumbers() {
// Given (Дано)
Calculator calculator = new Calculator();
int firstNumber = 2;
int secondNumber = 3;
// When (Когда)
int result = calculator.add(firstNumber, secondNumber);
// Then (То)
assertEquals(5, result);
}
Теперь сразу понятна цель теста: "должен вернуть сумму при сложении двух положительных чисел".
Использование с фреймворком Mockito
@Test
public void shouldUpdateUserWhenValidDataProvided() {
// Given
User user = new User(1, "John", "john@example.com");
UserRepository mockRepository = mock(UserRepository.class);
UserService userService = new UserService(mockRepository);
// When
userService.updateUser(user);
// Then
verify(mockRepository, times(1)).save(user);
verify(mockRepository, never()).delete(any());
}
Использование с фреймворком JUnit 5 и AssertJ
@Test
public void shouldReturnActiveUsersWhenFilteringByStatus() {
// Given
UserRepository repository = new InMemoryUserRepository();
repository.save(new User("Alice", UserStatus.ACTIVE));
repository.save(new User("Bob", UserStatus.INACTIVE));
repository.save(new User("Charlie", UserStatus.ACTIVE));
// When
List<User> activeUsers = repository.findByStatus(UserStatus.ACTIVE);
// Then
assertThat(activeUsers)
.hasSize(2)
.extracting(User::getName)
.containsExactlyInAnyOrder("Alice", "Charlie");
}
BDD с JBehave
Для полноценного BDD используется язык Gherkin (или похожие языки):
// Feature file (или прямо в коде)
public class UserAccountSteps {
private User user;
private UserService userService;
private boolean result;
@Given("пользователь с начальным балансом (\\d+) рублей")
public void givenUserWithBalance(int balance) {
user = new User();
user.setBalance(balance);
}
@When("пользователь совершает платёж (\\d+) рублей")
public void whenUserMakesPayment(int amount) {
result = userService.processPayment(user, amount);
}
@Then("баланс должен быть равен (\\d+) рублей")
public void thenBalanceShouldBe(int expectedBalance) {
assertEquals(expectedBalance, user.getBalance());
}
}
Сложный пример с исключениями
@Test
public void shouldThrowExceptionWhenDividingByZero() {
// Given
Calculator calculator = new Calculator();
int dividend = 10;
int divisor = 0;
// When & Then
assertThrows(ArithmeticException.class, () -> {
calculator.divide(dividend, divisor);
});
}
Преимущества Given-When-Then
- Читаемость: Тест легко понять даже не-программистам
- Структурированность: Ясное разделение подготовки, действия и проверки
- Безопасность: Меньше ошибок благодаря чёткой структуре
- Документация: Тесты служат живой документацией
- Сотрудничество: Бизнес-аналитики и разработчики говорят на одном языке
- Переиспользование: Легче переиспользовать код тестов
Best Practices
- Название теста должно отражать Given-When-Then:
shouldReturnErrorWhenAuthenticationFails - Не смешивай несколько When: Один тест = одно действие
- Используй осмысленные имена переменных: вместо
a,bиспользуйuser,product - Given должен быть простым: Сложная подготовка — признак проблем в дизайне
- Then должен проверить всё важное: Не забывай проверять побочные эффекты
Паттерн Given-When-Then — это мощный инструмент для написания понятных, поддерживаемых и эффективных тестов, что является критически важным в профессиональной разработке.