Piramida testów

#Java#Testy

Piramida testów to fundamentalne pojęcie w świecie wytwarzania oprogramowania. Warto jednak pamiętać, że to jedynie uproszczony model — rzeczywistość bywa bardziej złożona.

Czym jest piramida testów?

Piramida testów to wizualna metafora opisująca optymalny rozkład różnych typów testów automatycznych w projekcie. Zaproponowana przez Mike'a Cohna, zakłada, że:

  • dołem piramidy powinny być liczne, szybkie testy jednostkowe,
  • w środku umiarkowana liczba testów integracyjnych,
  • na szczycie nieliczne, ale kompleksowe testy E2E (end-to-end).

Kształt piramidy nieprzypadkowo jest trójkątem — im wyżej, tym mniej testów i tym droższe ich utrzymanie.

Testy jednostkowe (unit tests)

Testy jednostkowe to podstawa każdej strategii testowania. Testują pojedynczą jednostkę kodu — najczęściej metodę lub klasę — w izolacji od zewnętrznych zależności.

Cechy testów jednostkowych:

  • Działają w milisekundach
  • Nie wymagają bazy danych, sieci ani serwera
  • Są łatwe do pisania i utrzymania
  • Dają błyskawiczny feedback

W praktyce oznacza to mockowanie wszystkich zewnętrznych zależności i skupienie się wyłącznie na logice biznesowej. Przykład w Javie:

@Test
void shouldCalculateDiscountForPremiumCustomer() {
    // given
    Customer customer = new Customer(CustomerType.PREMIUM);
    Order order = new Order(BigDecimal.valueOf(1000));

    // when
    BigDecimal discount = discountCalculator.calculate(customer, order);

    // then
    assertThat(discount).isEqualByComparingTo(BigDecimal.valueOf(100));
}

Testy jednostkowe powinny stanowić zdecydowaną większość wszystkich testów w projekcie — mówi się o proporcji 70–80%.

Testy integracyjne

Testy integracyjne weryfikują współpracę kilku komponentów systemu. W ekosystemie Spring Boot najczęściej obejmują:

  • Spring Data — sprawdzają zapytania do bazy danych, mapowanie encji, repozytoria JPA
  • Spring MVC / Spring WebFlux — testują kontrolery, serializację JSON, obsługę błędów HTTP
  • Kontekst Spring — weryfikują konfigurację beanów i wstrzykiwanie zależności
@DataJpaTest
class OrderRepositoryTest {

    @Autowired
    private OrderRepository orderRepository;

    @Test
    void shouldFindOrdersByCustomerId() {
        // given
        Order order = new Order(42L, OrderStatus.NEW);
        orderRepository.save(order);

        // when
        List<Order> found = orderRepository.findByCustomerId(42L);

        // then
        assertThat(found).hasSize(1);
    }
}

Testy integracyjne są wolniejsze niż jednostkowe (często kilka sekund), ale dają pewność, że komponenty dobrze ze sobą współpracują. Powinny stanowić 15–20% wszystkich testów.

Testy E2E (end-to-end)

Testy E2E symulują rzeczywistego użytkownika korzystającego z aplikacji. Uruchamiają pełne środowisko — serwer, bazę danych, a często też przeglądarkę — i wykonują scenariusze jak prawdziwy użytkownik.

Zalety testów E2E:

  • Weryfikują pełny przepływ biznesowy
  • Wykrywają problemy integracji na styku systemów
  • Testują UI i doświadczenie użytkownika

Wady:

  • Są powolne (minuty, nie sekundy)
  • Trudniejsze do debugowania przy awarii
  • Bardziej podatne na niestabilność (tzw. flaky tests)

Ze względu na koszty, testów E2E powinno być relatywnie mało — skupionych na krytycznych ścieżkach biznesowych.

Strategia: jak ułożyć testy?

Przyjmując piramidę testów jako punkt wyjścia, rozsądna strategia wygląda następująco:

| Typ testu | Udział | Czas wykonania | |-----------|--------|----------------| | Jednostkowe | ~70% | milisekundy | | Integracyjne | ~20% | sekundy | | E2E | ~10% | minuty |

Kluczowe zasady:

  1. Testuj logikę biznesową jednostkowo — nie potrzebujesz Springa, żeby sprawdzić, czy rabat jest poprawnie naliczony.
  2. Testuj integrację z infrastrukturą — baza danych, zewnętrzne API, messaging — to najlepsze pole dla testów integracyjnych.
  3. Testuj E2E tylko krytyczne ścieżki — rejestracja, płatność, kluczowe przepływy biznesowe.

Podsumowanie

Piramida testów to nie dogmat, ale użyteczna heurystyka. Mówi nam: inwestuj w szybkie, tanie testy jednostkowe, bo dają największy zwrot z inwestycji. Uzupełniaj je testami integracyjnymi tam, gdzie testujesz granice systemu. Testy E2E traktuj jak ostatnią linię obrony dla najważniejszych scenariuszy.

W kolejnym wpisie zastanowię się, czy w dzisiejszych realiach — z Dockerem, TestContainers i nowoczesnymi frameworkami — piramida nadal ma sens.