Testowanie oprogramowania - kompendium
Testy mają dostarczać informacji o ryzyku, a nie tylko zwiększać licznik coverage. Dobry zestaw testów łączy szybkie testy małych fragmentów logiki z testami integracyjnymi i kilkoma ważnymi scenariuszami end-to-end.
Powiązane tematy: C - czytanie, kompilacja i debugowanie, Go - czytanie kodu, JavaScript, Node.js, Python oraz API i integracje systemów.
1. Po co testy
Testy mają zmniejszać ryzyko regresji i dostarczać informacji o jakości systemu.
Nie chodzi o maksymalną liczbę testów, lecz o dobre pokrycie ryzyka.
2. Poziomy testów
Najczęściej:
- unit,
- integration,
- end-to-end,
- smoke,
- regression,
- acceptance.
3. Unit test
Testuje mały fragment logiki w izolacji.
Przykład:
calculatePrice()
validateEmail()
parseConfig()
Zalety:
- szybkie,
- precyzyjne,
- łatwe do uruchomienia.
4. Integration test
Sprawdza współpracę kilku elementów:
backend + database
service + API client
router + handler
5. E2E
Testuje system z perspektywy użytkownika:
browser
→ frontend
→ backend
→ database
E2E są wartościowe, ale droższe i wolniejsze.
6. Smoke test
Krótki zestaw testów:
czy aplikacja wstaje?
czy homepage działa?
czy login działa?
Dobry po deploymencie.
7. Regression test
Sprawdza, czy wcześniejsze funkcje nadal działają po zmianie.
8. Test pyramid
Klasyczna idea:
E2E
integration
unit
Więcej szybkich testów niż drogich E2E.
Nie jest to sztywne prawo.
9. Arrange / Act / Assert
Typowy układ:
Arrange - przygotuj dane
Act - wykonaj operację
Assert - sprawdź wynik
10. Mock
Mock udaje zależność.
Przykład:
prawdziwe API płatności
↓
mock API
Mocki pomagają izolować, ale ich nadmiar może tworzyć testy oderwane od rzeczywistości.
11. Stub i fake
Stub: - zwraca przygotowaną odpowiedź.
Fake: - uproszczona działająca implementacja.
12. Co testować
Najpierw:
- krytyczną logikę,
- przypadki brzegowe,
- bugi, które już wystąpiły,
- kontrakty API,
- integracje,
- najważniejsze user flows.
13. Co zwykle ma mały sens
- testowanie frameworka,
- testy identyczne z implementacją,
- testy tylko dla procentu coverage.
14. Coverage
Coverage mówi, jaka część kodu została wykonana przez testy.
Nie mówi, czy testy są dobre.
100% coverage nie gwarantuje jakości.
15. Testowanie Go
Podstawowo:
go test ./...
Verbose:
go test -v ./...
Race detector:
go test -race ./...
16. Testowanie JavaScript
Popularne narzędzia:
- Vitest,
- Jest,
- Testing Library.
Ważne jest testowanie zachowania, nie szczegółów implementacji.
17. Playwright
Playwright pozwala automatyzować przeglądarkę.
Przykładowy flow:
wejdź na stronę
kliknij Login
wpisz dane
wyślij
sprawdź wynik
18. API testing
Testuj:
- status,
- body,
- headers,
- walidację,
- błędy,
- autoryzację.
19. Test data
Dane testowe powinny być:
- kontrolowane,
- powtarzalne,
- niezależne od produkcji.
20. Flaky tests
Flaky test raz przechodzi, raz nie.
Przyczyny:
- timing,
- zależność od sieci,
- shared state,
- data race,
- kolejność testów.
Flaky testy obniżają zaufanie do całego CI.
21. Test isolation
Test powinien dawać ten sam wynik niezależnie od kolejności uruchomienia.
22. Fixtures
Fixtures przygotowują dane lub środowisko.
Nie rób z fixture ogromnego magicznego świata trudnego do zrozumienia.
23. CI
Dobry pipeline:
format
→ lint
→ unit
→ integration
→ build
→ opcjonalnie E2E
24. Manual testing
Automatyzacja nie zastępuje całkowicie ręcznego sprawdzenia.
Manual jest dobry dla:
- UX,
- nowych funkcji,
- eksploracji,
- przypadków trudnych do przewidzenia.
25. Checklist przed releasem
- testy przechodzą,
- build działa,
- migracje sprawdzone,
- smoke test,
- najważniejszy flow użytkownika,
- logi bez nowych błędów,
- rollback możliwy.
26. Co trzeba umieć
- odróżnić unit/integration/E2E,
- dobrać poziom testu,
- rozumieć mocki,
- uruchamiać testy w CI,
- rozpoznawać flaky tests,
- pisać testy najważniejszych zachowań.
Oficjalne źródła
- Go testing package: https://pkg.go.dev/testing
- Node.js test runner: https://nodejs.org/api/test.html
- pytest documentation: https://docs.pytest.org/
- Playwright documentation: https://playwright.dev/docs/intro