Rodzaje testów i kiedy je stosować
Unit, integration, E2E, manual, exploratory — każdy rodzaj ma swoje miejsce. Poznaj debatę test pyramid vs testing trophy i jak robić właściwe kompromisy.
“Powinniśmy mieć więcej testów.”
Każdy programista powiedział to po incydencie produkcyjnym. Ale więcej testów nie znaczy lepsze testy. Zły rodzaj testu dla danego problemu jest drogi, wolny i ostatecznie mylący. Rozumienie, kiedy używać jakiego rodzaju testów, to jedna z najcenniejszych umiejętności w inżynierii oprogramowania — i rzadko jest jawnie nauczana.
W tym artykule omówię pięć podstawowych rodzajów testów, wyjaśnię debatę między test pyramid a testing trophy i dam Ci praktyczną ramę do wyboru właściwego narzędzia do danej roboty.
Pięć podstawowych rodzajów testów
Testy jednostkowe (Unit Tests)
Test jednostkowy weryfikuje pojedynczą jednostkę kodu — zazwyczaj funkcję, metodę lub klasę — w izolacji od jej zależności.
Charakterystyka:
- Najszybsze do uruchomienia (milisekundy na test)
- Całkowicie deterministyczne — żadnych operacji I/O, sieci, bazy danych
- Zależności są zastępowane przez test doubles (mocki, stuby, fałszywe implementacje)
- Łatwe do diagnozowania gdy nie przechodzą
Kiedy stosować: Zawsze, dla całej logiki biznesowej. Jeśli funkcja podejmuje decyzję, powinna mieć test jednostkowy. To nie podlega dyskusji.
Narzędzia: xUnit, NUnit, MSTest (.NET) · Jest, Vitest (JavaScript) · pytest (Python)
Co pomijają: Problemy integracyjne. Test jednostkowy może weryfikować, że Twój kod poprawnie wywołuje metodę bazy danych — ale nie powie Ci, czy SQL jest poprawny.
Testy integracyjne (Integration Tests)
Test integracyjny weryfikuje, że wiele komponentów poprawnie ze sobą współpracuje. Może to oznaczać: serwis + baza danych, dwa mikroserwisy komunikujące się ze sobą, aplikacja + zewnętrzne API.
Charakterystyka:
- Wolniejsze niż testy jednostkowe (sekundy na test)
- Mogą angażować prawdziwe operacje I/O — rzeczywiste wywołania bazy danych, prawdziwe żądania HTTP
- Bardziej złożony setup i teardown
- Większa pewność co do zachowania systemu
Kiedy stosować: Do weryfikacji przepływów danych, kontraktów między komponentami i interakcji z bazą danych. Po tym, jak testy jednostkowe dają pewność co do logiki, testy integracyjne potwierdzają, że komponenty poprawnie się łączą.
Narzędzia: TestContainers (rzeczywista baza w Dockerze dla testów) · WebApplicationFactory (.NET in-memory API) · Supertest (testowanie API w Node.js)
Testy end-to-end (E2E)
Testy E2E sterują pełnym systemem z perspektywy użytkownika — od przeglądarki do bazy danych i z powrotem.
Charakterystyka:
- Najwolniejszy rodzaj testów (sekundy do minut na test)
- Najwyższy koszt utrzymania — psują się przy każdej zmianie UI
- Najwyższa pewność — jeśli przechodzi, prawdziwy użytkownik może odnieść sukces
- Najbardziej podatne na niestabilność (flakiness)
Kiedy stosować: Tylko dla krytycznych ścieżek użytkownika. Logowanie. Checkout. Podstawowy przepływ biznesowy. Nie dla każdego kliknięcia przycisku.
Narzędzia: Playwright · Cypress · Selenium WebDriver
Pułapka: Zespoły piszące testy E2E dla wszystkiego kończą z suitami trwającymi godziny, psującymi się stale i ignorowanymi gdy nie przechodzą. Testy E2E są drogie — traktuj je jak drogie.
Testowanie manualne (Manual Testing)
Testowanie manualne to testowanie sterowane przez człowieka, oparte na osądzie. Tester wchodzi w interakcję z systemem, obserwując zachowanie i stosując własne doświadczenie.
Charakterystyka:
- Z definicji nie do zautomatyzowania — wartością jest ludzki osąd
- Najlepsze dla oceny UX, dostępności, reakcji emocjonalnej
- Dobre dla sesji eksploracyjnych na nowych funkcjach
Kiedy stosować: Nowe funkcje przed napisaniem automatyzacji. Ocena UX i użyteczności. Audyt dostępności. Testy akceptacyjne z prawdziwymi interesariuszami.
Nieporozumienie: Testowanie manualne jest często postrzegane jako fallback — “nie mieliśmy czasu zautomatyzować.” Ale dobre testowanie manualne to celowa, wykwalifikowana aktywność. To nie jest gorsza forma testowania; to inna forma.
Exploratory Testing (Testowanie eksploracyjne)
Exploratory testing to jednoczesne uczenie się, projektowanie testów i wykonywanie. Tester nie podąża według skryptu — używa swojej wiedzy o systemie do badania obszarów ryzyka.
Charakterystyka:
- Nieoskryptowane, ale ustrukturyzowane (chartery testowe nadają kierunek)
- Znajduje bugi, które przeoczają testy oskryptowane
- Wysokie wymagania dotyczące umiejętności — wiedza testera bezpośrednio wpływa na to, co znajdzie
- Uzupełnia testy oskryptowane; ich nie zastępuje
Kiedy stosować: Po wydaniach nowych funkcji. Po dużych refaktorach. Przed większymi wydaniami. Kiedy coś “nie gra”, ale nie możesz tego sprecyzować.
Exploratory testing omawiam szczegółowo w artykule o profesjonalnym podejściu do tej techniki.
Test Pyramid vs Testing Trophy
To jeden z najbardziej dyskutowanych tematów we współczesnej strategii testowania.
Klasyczny Test Pyramid (Mike Cohn, 2009)
/\
/E2E\ ← mało, wolne, drogie
/------\
/ Integr.\ ← trochę, średnia prędkość
/------------\
/ Testy jedn. \ ← dużo, szybkie, tanie
/------------------\
Uzasadnienie: Testy jednostkowe są tanie do pisania, uruchomienia i utrzymania. Im wyżej w piramidzie, tym droższy test. Miej więc dużo tanich testów i mało drogich.
Mocne strony: Szybki feedback w CI. Łatwe w utrzymaniu. Jasna własność (programista pisze testy jednostkowe).
Słabe strony: System z 2000 testami jednostkowymi i 5 integracyjnymi nadal może się wysypywać przy integracji. Testy jednostkowe nie wykrywają bugów integracyjnych.
Testing Trophy (Kent C. Dodds, 2018)
/\
/E2E\ ← mało
/------\
/ Integr.\ ← WIĘKSZOŚĆ testów tutaj
/------------\
/ Jednostkowe \ ← trochę
/------------------\
[ Analiza statyczna] ← fundament
Uzasadnienie: Testy integracyjne dają najlepszy stosunek pewności do kosztu. Testują system blisko sposobu, w jaki jest faktycznie używany, bez overhead i niestabilności E2E.
Cytat: “Im bardziej Twoje testy przypominają sposób, w jaki Twoje oprogramowanie jest używane, tym więcej pewności Ci dają.” — Kent C. Dodds
Mocne strony: Wysoka pewność. Testy przeżywają refaktory (testują zachowanie, nie implementację).
Słabe strony: Wolniejsze niż testy jednostkowe. Trudniejszy setup. Mniej przydatne dla czystej logiki biznesowej.
Lody (Ice Cream Cone) — anty-wzorzec
/------------------------\
/ Testowanie manualne \ ← dużo
/----------------------------\
\ Testy E2E / ← trochę
\--------------------------/
\ Integracyjne / ← mało
\----------------------/
\ Jednostkowe / ← prawie wcale
\------------------/
Zespoły lądują tutaj przez przypadek: QA robi testowanie manualne, bo “nie ma czasu na automatyzację”, skrypty E2E istnieją sprzed epoki, gdy ktokolwiek dbał o wydajność, i nikt nie pisał testów jednostkowych, bo “tak tu nie robimy.”
Konsekwencje: Wolne CI, niestabilne testy, wysoki koszt utrzymania, brak szybkiej pętli feedbacku. Każde PR potrzebuje 30 minut do weryfikacji.
Ostrzeżenie: Lody (ice cream cone) to nie jest strategia. Jeśli Twój pipeline CI trwa ponad 20 minut, a najwolniejszy krok to “uruchom testy E2E,” masz problem z kształtem testów. Napraw kształt zanim dodasz więcej testów.
Wybór kształtu
Szczera odpowiedź brzmi: to zależy. Kształt Twojego portfolio testów powinien odzwierciedlać architekturę, rozmiar zespołu i profil ryzyka.
| Kontekst | Zalecany kształt |
|---|---|
| Mikroserwisy z jasnymi kontraktami | Więcej integracyjnych, mniej E2E |
| Aplikacja frontendowa oparta na React | Testing trophy — komponent + integracyjne |
| Biblioteka z logiką biznesową | Piramida — duże pokrycie jednostkowe |
| Legacy system bez testów | Zacznij od E2E (smoke), dodawaj jednostkowe przy refaktorze |
| Regulowana branża | Wszystkie warstwy + formalna dokumentacja |
Macierz kompromisów
| Wymiar | Jednostkowe | Integracyjne | E2E | Manualne |
|---|---|---|---|---|
| Prędkość | ⚡ Szybkie | 🔶 Średnie | 🐢 Wolne | 🐢 Wolne |
| Koszt pisania | Niski | Średni | Wysoki | Brak |
| Koszt utrzymania | Niski | Średni | Wysoki | Brak |
| Poziom pewności | Niski | Średni | Wysoki | Wysoki |
| Ryzyko niestabilności | Bardzo niskie | Niskie-średnie | Wysokie | N/A |
| Wykrywa bugi integracyjne | ❌ | ✅ | ✅ | ✅ |
| Wykrywa problemy UX | ❌ | ❌ | Częściowo | ✅ |
Praktyczne rekomendacje
Przed napisaniem jakiegokolwiek nowego testu:
- Zidentyfikuj ryzyko — co ma największe prawdopodobieństwo zepsucia? Co kosztuje najbardziej przeoczyć?
- Wybierz najtańszy rodzaj testu, który adekwatnie pokrywa to ryzyko
- Jeśli testy jednostkowe dają wystarczającą pewność, nie pisz E2E
Sprawdzenie ROI: Przed automatyzacją testu zapytaj: “Jak często to wykryje prawdziwy błąd vs jak długo będzie zajmować utrzymanie?” Jeśli odpowiedź to “rzadko” i “często” — nie automatyzuj.
Podsumowanie
“Właściwy” kształt portfolio testów nie istnieje w abstrakcji — istnieje dla Twojego produktu, Twojego zespołu, Twojej tolerancji na ryzyko i częstotliwości wdrożeń. Ale zły kształt ma wyraźną sygnaturę: wolne buildy, ignorowane błędy i incydenty, które “testy powinny były wykryć.”
Zacznij od audytu: narysuj aktualny kształt swojego portfolio testów. Czy to piramida? Trophy? Lody? Gdy już wiesz, gdzie jesteś, możesz zdecydować, gdzie chcesz być — i zrobić jeden konkretny krok w tym kierunku w tym sprincie.
To jest trzeci artykuł z serii Seria 1 — QA Ogólne.