middle
Что такое TDD и BDD? Чем они отличаются?
TDD (Test-Driven Development) — разработка через тестирование, методология, в которой тесты пишутся до реализации кода. BDD (Behavior-Driven Development) — расширение TDD, фокусирующееся на описании поведения системы с точки зрения бизнеса.
Цикл TDD (Red-Green-Refactor)
- Red — написать тест, который не проходит (реализации ещё нет)
- Green — написать минимальный код, чтобы тест прошёл
- Refactor — улучшить код, не меняя поведение, убедившись, что тесты проходят
Пример цикла TDD
// Шаг 1 (Red): пишем тест
@Test
void shouldCalculateDiscount() {
PriceCalculator calculator = new PriceCalculator();
BigDecimal result = calculator.calculatePrice(new BigDecimal("1500"));
assertEquals(new BigDecimal("1350.00"), result);
}
// Шаг 2 (Green): минимальная реализация
public class PriceCalculator {
public BigDecimal calculatePrice(BigDecimal amount) {
if (amount.compareTo(new BigDecimal("1000")) > 0) {
return amount.multiply(new BigDecimal("0.90"))
.setScale(2, RoundingMode.HALF_UP);
}
return amount;
}
}
// Шаг 3 (Refactor): улучшаем код
public class PriceCalculator {
private static final BigDecimal DISCOUNT_THRESHOLD = new BigDecimal("1000");
private static final BigDecimal DISCOUNT_RATE = new BigDecimal("0.10");
public BigDecimal calculatePrice(BigDecimal amount) {
if (amount.compareTo(DISCOUNT_THRESHOLD) > 0) {
BigDecimal discount = amount.multiply(DISCOUNT_RATE);
return amount.subtract(discount).setScale(2, RoundingMode.HALF_UP);
}
return amount;
}
}
BDD — формат Given-When-Then
Пример
@Nested
@DisplayName("Оформление заказа")
class OrderPlacement {
@Test
@DisplayName("Учитывая корзину с товарами, когда пользователь оформляет заказ, тогда заказ создаётся")
void givenCartWithItems_whenPlaceOrder_thenOrderIsCreated() {
// Given (Дано)
Cart cart = new Cart();
cart.addItem(new Product("Книга", new BigDecimal("500")));
cart.addItem(new Product("Ручка", new BigDecimal("50")));
// When (Когда)
Order order = orderService.placeOrder(cart, user);
// Then (Тогда)
assertThat(order).isNotNull();
assertThat(order.getStatus()).isEqualTo(OrderStatus.CREATED);
assertThat(order.getTotalAmount()).isEqualByComparingTo("550");
}
}
BDD-стиль с Mockito (BDDMockito)
Пример
import static org.mockito.BDDMockito.*;
@Test
void shouldProcessPayment() {
// Given
given(paymentGateway.charge(any(PaymentRequest.class)))
.willReturn(new PaymentResponse(true, "txn-123"));
// When
PaymentResult result = paymentService.processPayment(order);
// Then
then(paymentGateway).should().charge(any(PaymentRequest.class));
assertThat(result.isSuccessful()).isTrue();
}
Основные различия
| Критерий | TDD | BDD |
|---|---|---|
| Фокус | Корректность кода | Поведение системы |
| Формат | Test -> Implement -> Refactor | Given -> When -> Then |
| Терминология | Test, Assert | Specification, Should, Given/When/Then |
| Целевая аудитория | Разработчики | Разработчики, QA, бизнес |
| Инструменты | JUnit, Mockito | JUnit + BDDMockito, Cucumber, Spock |
| Уровень | Юнит-тесты | Юнит и приёмочные тесты |
На собеседовании: важно объяснить цикл Red-Green-Refactor для TDD и формат Given-When-Then для BDD. Частая ошибка — считать, что BDD заменяет TDD. На самом деле BDD — это расширение TDD с фокусом на бизнес-поведение.