Gymterview
middle

Что такое TDD и BDD? Чем они отличаются?

TDD (Test-Driven Development) — разработка через тестирование, методология, в которой тесты пишутся до реализации кода. BDD (Behavior-Driven Development) — расширение TDD, фокусирующееся на описании поведения системы с точки зрения бизнеса.

Цикл TDD (Red-Green-Refactor)

  1. Red — написать тест, который не проходит (реализации ещё нет)
  2. Green — написать минимальный код, чтобы тест прошёл
  3. 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 с фокусом на бизнес-поведение.