← Назад к вопросам

К какому уровню тестовой пирамиды относятся unit тесты

2.2 Middle🔥 111 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Unit тесты в пирамиде тестирования

Пирамида тестирования (Test Pyramid)

Пирамида тестирования — это структура, которая показывает, в каком соотношении должны быть разные типы тестов:

         /\
        /E2E\
       /-----\
      /  UI  \
     /-------\ 
    /Integration\
   /-----------\
  /  Unit      \
 /_______________\

Unit тесты — это основание пирамиды

Unit тесты расположены в самом низу, потому что они:

// Unit тест — быстрый, изолированный, дешёвый
@Test
public void testCalculateDiscount() {
    // Arrange
    DiscountCalculator calculator = new DiscountCalculator();
    
    // Act
    double discount = calculator.apply(100, 0.1);
    
    // Assert
    assertEquals(10, discount, 0.01);
}
// Выполняется за миллисекунды

Характеристики Unit тестов

1. Быстрота Unit тесты выполняются за миллисекунды:

// Быстро
@Test
public void testStringUtils() {
    String result = StringUtils.truncate("hello", 2);
    assertEquals("he", result);
}

// Медленно — это уже не unit тест
@Test
public void testWithDatabaseCall() {
    database.connect(); // медленно
    userRepository.save(user); // медленно
    // это интеграционный тест
}

2. Изолированность Unit тесты проверяют одну функцию/класс в изоляции:

public class OrderService {
    private final PaymentProcessor paymentProcessor;
    private final NotificationService notificationService;
    
    public OrderService(PaymentProcessor paymentProcessor, 
                        NotificationService notificationService) {
        this.paymentProcessor = paymentProcessor;
        this.notificationService = notificationService;
    }
    
    public void processOrder(Order order) {
        paymentProcessor.charge(order);
        notificationService.notifyCustomer(order);
    }
}

// Unit тест — мокируем зависимости
@Test
public void testProcessOrder() {
    // Arrange
    PaymentProcessor mockPaymentProcessor = mock(PaymentProcessor.class);
    NotificationService mockNotificationService = mock(NotificationService.class);
    OrderService service = new OrderService(mockPaymentProcessor, mockNotificationService);
    Order order = new Order(100);
    
    // Act
    service.processOrder(order);
    
    // Assert — проверяем, что методы вызваны, но не реально
    verify(mockPaymentProcessor).charge(order);
    verify(mockNotificationService).notifyCustomer(order);
}

3. Независимость Unit тесты не зависят друг от друга:

@Test
public void testAdd() {
    Calculator calc = new Calculator();
    assertEquals(5, calc.add(2, 3));
}

@Test
public void testSubtract() { // этот тест работает независимо
    Calculator calc = new Calculator();
    assertEquals(1, calc.subtract(3, 2));
}

Сравнение с другими уровнями пирамиды

Unit тесты (основание)

@Test
public void testUserValidator() {
    // Only logic, no dependencies
    UserValidator validator = new UserValidator();
    assertTrue(validator.isValidEmail("test@example.com"));
    assertFalse(validator.isValidEmail("invalid"));
}

Характеристики:

  • Количество: много (70-80%)
  • Скорость: очень быстрые (< 1ms)
  • Стоимость: дешевые
  • Фокус: бизнес-логика
  • Инструменты: JUnit, Mockito, AssertJ

Integration тесты (средний уровень)

@SpringBootTest
public class UserRepositoryIntegrationTest {
    @Autowired
    private UserRepository userRepository;
    
    @Test
    public void testSaveAndFindUser() {
        // Реально используем БД
        User user = new User("John", "john@example.com");
        userRepository.save(user);
        
        // Проверяем что в БД
        Optional<User> found = userRepository.findByEmail("john@example.com");
        assertTrue(found.isPresent());
    }
}

Характеристики:

  • Количество: меньше (15-20%)
  • Скорость: медленнее (100-500ms)
  • Стоимость: дороже
  • Фокус: интеграция компонентов
  • Инструменты: @SpringBootTest, TestContainers

E2E / UI тесты (вершина)

public class UserSignupE2ETest {
    @Test
    public void testCompleteSignupFlow() {
        // Открываем браузер, заполняем форму и т.д.
        driver.get("https://example.com");
        driver.findElement(By.id("email")).sendKeys("test@example.com");
        driver.findElement(By.id("signup")).click();
        
        // Проверяем финальный результат
        assertEquals("Success", driver.findElement(By.id("message")).getText());
    }
}

Характеристики:

  • Количество: мало (5-10%)
  • Скорость: медленные (секунды-минуты)
  • Стоимость: очень дорогие
  • Фокус: пользовательский сценарий
  • Инструменты: Selenium, Playwright

Почему unit тесты в основании?

Скорость выполнения:
Unit:           0-1ms          ████ быстро
Integration:    100-500ms      ███████████ медленнее
E2E:            5-30s          ██████████████████████████ очень медленно

Стоимость:
Unit:           дешевые        ███
Integration:    дороже         ██████
E2E:            очень дорогие  ████████████

Одновременное выполнение:
Unit:           100+ тестов    за секунды
Integration:    20 тестов      за минуту
E2E:            10 тестов      за 10 минут

Правильное соотношение в пирамиде

🏆 E2E (5-10%)    — только критичные сценарии
   Integration (15-20%)  — интеграция компонентов
   Unit (70-80%)         — всё остальное

Плохо:

      E2E (40%)        — медленные тесты, долгий feedback
      Integration (40%) — дорого и медленно
      Unit (20%)       — недостаточно

Практический пример иерархии

// 1. Unit тест — логика платежа
@Test
public void testDiscountCalculation() {
    Order order = new Order();
    assertEquals(10, order.calculateDiscount(100, 0.1));
}

// 2. Integration тест — платёж + БД
@SpringBootTest
public class PaymentIntegrationTest {
    @Test
    public void testSavePayment() {
        paymentRepository.save(payment);
        assertTrue(paymentRepository.exists(payment.getId()));
    }
}

// 3. E2E тест — весь процесс
@Test
public void testCompletePaymentFlow() {
    driver.get("https://shop.com/checkout");
    driver.findElement(By.id("amount")).sendKeys("100");
    driver.findElement(By.id("pay")).click();
    assertEquals("Payment successful", driver.findElement(By.id("message")).getText());
}

Почему unit тесты важны?

  1. Быстрый feedback — узнаёшь об ошибке за 1 секунду
  2. Дешевы в разработке — не нужно настраивать БД, браузер и т.д.
  3. Высокая скорость выполнения — можешь запустить их 100 раз
  4. Простота отладки — легко найти проблему в 10 строк кода
  5. Тестируют бизнес-логику — самая важная часть

Антипаттерн: тестовая пирамида вверх ногами

Плохо:                    Хорошо:
E2E 50%                    E2E 10%
Integration 40%            Integration 20%
Unit 10%                   Unit 70%

Вывод

Unit тесты — это основание пирамиды тестирования:

  • Их должно быть 70-80% от всех тестов
  • Они выполняются быстро (мс)
  • Они дешевы в разработке
  • Они тестируют бизнес-логику в изоляции
  • Они дают быстрый feedback на ошибки

Структура пирамиды гарантирует:

  • Быстрый feedback при разработке
  • Покрытие всех слоёв приложения
  • Баланс между скоростью и надёжностью
  • Дешевизну поддержки автотестов
К какому уровню тестовой пирамиды относятся unit тесты | PrepBro