Testy bazujące na obserwacji rzeczywistości

Testy bazujące na obserwacji rzeczywistości
Dodawanie testów do istniejącego kodu to nie tylko wyzwanie techniczne, ale też poznawcze. Zamiast zgadywać, co robi system, możesz go po prostu przetestować. Testowanie empiryczne to technika, która pozwala to zrobić bez ryzyka.

Choć w teorii najlepiej pisać testy równolegle z kodem, w praktyce znaczna część systemów, z którymi pracujemy, powstała zupełnie inaczej. Właśnie wtedy pojawia się potrzeba testowania po fakcie, czyli testów, które nie weryfikują wymagań, lecz opisują aktualne zachowanie systemu. Nie pytają: „czy działa dobrze?”, tylko: „czy działa tak, jak działało przed chwilą?”. To podejście nosi nazwę testowanie charakterystyki empirycznej (ang. Empirical Characterization Testing) i jest jednym z najbezpieczniejszych sposobów pracy z kodem legacy. 

Czym są testy charakterystyki?

Testy charakterystyki (ang. Characterization Tests) to testy dodawane do istniejącego kodu; takiego, którego działania nie jesteśmy do końca pewni. Zamiast sprawdzać zgodność ze specyfikacją, zapisują one to, co kod faktycznie robi w danym momencie. To rodzaj automatycznej dokumentacji: jeśli kiedyś coś się zmieni, test powie nam, że zachowanie było inne niż wcześniej. To bezcenna informacja przy refaktoryzacji, dodawaniu nowych funkcji lub usuwaniu długów technicznych. 

Test jako dowód

Testy są często traktowane jako narzędzie walidacji, tymczasem ich prawdziwa siła tkwi w czymś innym. Działający test to eksperyment, który potwierdza hipotezę, że „system zachowuje się w określony sposób”. To podejście bliskie nauce: nie udowadniamy, że coś działa, ale zbieramy dowody, które sugerują, że nie popsuliśmy tego, co działało wcześniej. 

W tym sensie testy nie są deklaracją poprawności, lecz formą ostrożności, a także narzędziem zbierania wiedzy.

Jak napisać test charakterystyki

W pracy z kodem bez testów można przyjąć jedno z dwóch podejść. Oba mają swoje miejsce i zależą od preferencji, kontekstu i poziomu ryzyka. 

1. Metoda klasyczna (wg Michaela Feathersa):
  1. umieść fragment kodu w testach jednostkowych lub integracyjnych,
  2. napisz asercję, która celowo nie przejdzie, 
  3. sprawdź, jak kod faktycznie się zachowuje (co zwraca, co zmienia),
  4. zmień test tak, aby pasował do rzeczywistego zachowania, 
  5. powtórz ten proces dla kolejnych przypadków. 

Zaletą tego podejścia jest jego prostota i szybkość, a wadą ryzyko, że przypadkowo napiszesz test, który przechodzi, ale niczego realnie nie weryfikuje. Zwłaszcza gdy zmieniasz asercję „na oko”, bez wcześniejszego błędu, który by cię zatrzymał. 

2. Metoda z „kontrolowanym sabotażem”:
  1. napisz test z docelową asercją (taką, która zakłada poprawne zachowanie),
  2. uruchom test i upewnij się, że przechodzi, 
  3. celowo uszkodź kod produkcyjny (np. usuń linijkę odpowiedzialną za zapis do bazy danych), 
  4. sprawdź, czy test teraz nie przechodzi i czy błąd występuje dokładnie tam, gdzie oczekujesz, 
  5. przywróć kod do pierwotnego stanu, 
  6. uruchom test ponownie, by upewnić się, że znów przechodzi. 

Ten sposób jest bardziej czasochłonny, ale zmniejsza ryzyko przypadkowych lub tautologicznych testów, które nie mają pokrycia w rzeczywistości. 

W obu przypadkach testy pełnią tę samą funkcję: zabezpieczają obecne działanie systemu i tworzą bazę wiedzy, która pozwala pracować dalej bez zgadywania i domysłów. 

Kiedy stosować?

Podejście empiryczne (doświadczeniowe) sprawdza się szczególnie dobrze, gdy:

  • pracujesz z kodem bez testów lub z testami o niskim pokryciu, 
  • nie masz dokumentacji lub nie ufasz tj. która istnieje, 
  • przygotowujesz refaktoryzację i chcesz się zabezpieczyć,
  • dodajesz nowe funkcje, które bazują na starym zachowaniu, 
  • przejmujesz projekt po kimś i nie masz jeszcze pełnej wiedzy o systemie. 

W takich przypadkach testy charakterystyki nie tylko chronią kod przed przypadkowymi zmianami, ale też pomagają ci lepiej zrozumieć działanie systemu. To testy, które uczą nie tylko maszynę, ale i ciebie. 

Nie zatrzymuj się jednak jedynie na testowaniu kodu. Podejście empiryczne równie dobrze sprawdzi się w testowaniu po interfejsie. 

Wnioski

Empiryczne testowanie to jedno z najbardziej pragmatycznych i skutecznych podejść w pracy z kodem, który powstał bez odpowiedniego wsparcia testowego. Nie zakłada wiedzy, nie wymaga zaufania, zaczyna się od obserwacji i dopiero potem pozwala na modyfikację.
 

Jaką funkcję pełnią testy w Twoim zespole?
Jaką funkcję pełnią testy w Twoim zespole?
0 %
Są formą dokumentacji zachowania
0 %
Są głównie walidacją wymagań
100 %
Są głównie zabezpieczeniem regresji
0 %
Są traktowane raczej formalnie
Łącznie głosów: 2
Źródła:
https://blog.ploeh.dk/2025/11/03/empirical-characterization-testing/

To powinno Cię zainteresować