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

2014-01-10 10:14
foo
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?

Pozostało 580 znaków

2014-01-10 10:54
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.

Pozostało 580 znaków

2014-01-10 11:01
foo
0

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

Pozostało 580 znaków

2014-01-10 11:10
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
  4. Wywołujesz metodę addUser z UserService z poprawnymi danymi.
  5. 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.

Pozostało 580 znaków

2014-01-10 11:15
foo
2

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

Wielkie Dzięki!

Pozostało 580 znaków

2014-01-10 11:16
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.


Masz problem? Pisz na forum, nie do mnie. Nie masz problemów? Kup komputer...

Pozostało 580 znaków

Liczba odpowiedzi na stronę

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