Testy integracyjne - jak je z głową tworzyć?

0

Dotychczas wszystko co dało się testować po klasie TestCase traktowałem jako test jednostkowy. Nie nieważne było jak bardzo złożona była ta testowana "jednostka". Czasem była prosta funkcja, a czasem klasa, która korzystała z wielu wcześniej stworzonych klas. Proste przypadki łatwo szło testowało, a te drugi już niezbyt i w związku z tym bardzo często korzystałem z mocków lub zmieniałem API po to, żeby dało się wstrzykiwać zależności.

Od tygodnia zorientowałem się, że źle rozumiem znaczenie testów jednosktowych. Sam test jednostkowy powinien testować tylko jednostkę w izolacji - czyli zdala od moich pozostałych klas.

Natomiast te drugie testy z którymi walczę do dziś to ponoć testy integracyjne. Fajną wieścią w ich przypadku jest to, że tutaj mogę sobie pozwolić na hity do bazy danych, czytanie z plików i łączenie z siecią, ponieważ wtedy nie muszę tak bardzo popadać w mockowanie.

Mimo, że celem tych testów jest sprawdzenie czy dobrze zintegrowałem ze sobą moje klasy to tak naprawdę nie wiem jak mam test prowadzić.

Przykładowo mam klasę Foo, korzysta ona z ustawień aplikacji i kilku innych dużo prostszych klas, które już wcześniej przetestowałem. Szansa, że ktoś użyje bezpośrednio klasę Foo jest moim zdaniem 100 razy większa w stosunku do tych prostych klas.

Pytanie więc jak to testować? Przecież jeżeli klasę Foo będę testował bardzo szczegółowo to cały test będzie mało czytelny, będzie cieżki w utrzymaniu i będzie posiadał wiele kopii testów, które już wcześniej stworzyłem dla testów jednostkowych.

Z drugiej strony jeśli tylko sprawdzę pozytywny przypadek testu jednostkowego to pojawia się pytanie, co z pozostałymi testami dla których spodziewam się wyniku pozytywnego. No i co z tymi przypadkami dla których oczekuje wykrycia negatywnych danych?

0

Testem integracyjnym sprawdzasz współdziałanie klas, a tym samym większy nacisk kładziesz na przebieg procesu. Oczywiście ważne jest sprawdzenie rezultatów np. zapisu do bazy, utworzenia pliku itp. Nie testuj zatem pojedynczej funkcjonalności tak jak ma to miejsce w przypadku testów jednostkowych, ale cały scenariusz.

BTW, mocki są znane? Jak tak to pierwsze testy integracyjne powinny polegać na skopiowaniu testów jednostkowych i zastąpieniu mocków prawdziwymi obiektami.

0

Więc to oznacza, że nadal trzeba pisać testy jednostkowe, które testują bardzo złożone klasy?

3

TI to przede wszystkim testowanie "potoku", a nie "funkcji" sprawdzasz czy np. tworzenie klienta działa poprawnie. Interesuje cię to co powinno się stać dookoła.
Na przykładzie tego tworzenia klienta.

  1. Konfigurujesz sobie klasę testową UserServiceITest.
  2. W niej umieszczasz UserService do którego wstrzykujesz zależności np. UserValidator, UserDao, Logger
  3. Przygotowujesz i weryfikujesz stan środowiska:
  • czy baza danych jest pusta
  • czy plik logu nie posiada żadnych wpisów
  1. Wywołujesz metodę addUser z UserService z poprawnymi danymi.
  2. Weryfikujesz:
  • czy pojawił się rekord w bazie
  • czy pojawił się rekord w logu

Powtarzasz test dla niepoprawnych danych i weryfikujesz

  • czy pojawił się wpis w logu
  • czy NIE pojawił się wpis w bazie
  • czy metoda zwróciła poprawny komunikat o błędzie.
2

Zajebiste! Dopiero dzięki twojemu postowi załapałem: ** TEST INTEGRACYJNY TESTUJE STAN ŚRODOWISKA, A NIE ZACHOWANIE FUNKCJI!**

Wielkie Dzięki!

1

@foo wydaje mi się że próbujesz inkrementalnie przetestować "wszystko" w aplikacji, a to dość karkołomny pomysł. Testy jednostkowe klasy X sprawdzają czy klasa X liczy poprawnie jakieś wartości. Testy jednostkowe klasy Y sprawdzają czy poprawnie zapisuje ona wyniki do plików. Testy jednostkowe klasy V, która używa X oraz Y, polegają na mockowaniu X i Y i sprawdzeniu czy są wywoływane zgodnie z oczekiwaniami.

Zauważ że to oznacza że nie musisz już w trakcie testu integracyjnego skupiać się na tym czy X przechodzi takimi ścieżkami jakimi powinno i czy wylicza tak jak powinno, a Y zawsze poprawnie wykonuje sekwencje zapisywania wyników (bo musiałbyś zrobić 2n przypadków gdzie n to liczba klas które integrujesz). W teście integracyjnym masz użyć V z prawdziwymi obiektami X i Y w jakichś konkretnych, życiowych scenariuszach i sprawdzić czy wyniki się zgadzają. Tutaj w przeciwieństwie do testów jednostkowych możesz zrobić typowego black-boxa, czyli nie bawić się w sprawdzanie czy wszystko wywołuje się w dobrej sekwencji (to powinien sprawdzić test jednostkowy klasy V) tylko czy wszystko razem zadziałało.

1 użytkowników online, w tym zalogowanych: 0, gości: 1