Testy jednostkowe vs testy integracyjne

Odpowiedz Nowy wątek
2016-07-30 02:40
Krzywy Mariusz
1

Na ile mozna robic wszystko testami jednostkowymi a na ile integracyjnymi?

Czesto robilem ile sie da jednostkowymi + np. Cale CRUDy przez wszystkie warstwy integracyjnymi.

Niby spoko. Ale aplikacja puchnie. Testow coraz wiecej a odpalanie ich zajmuje coraz wiecej czasu.

Jak to wywazyc? Widzialem sugeste mockowania db layer... Ale w ten sposob nie wykryje problemow z transakcjami albo z konkretna baza danych...

Pozostało 580 znaków

2016-07-30 02:45
0

Jakie problemy z transakcjami albo bazą danych chcesz wykrywać w testach?


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."

Pozostało 580 znaków

2016-07-30 09:45
Krzywy Mariusz
0

Np. W integracyjnych zobacze lazy initialization exception. W jednostkowych nie.

Pozostało 580 znaków

2016-07-30 10:02
Krzywy Mariusz
0

Chce przetestowac poprawne interakcje na db. Zapis i poprawny odczyt, ze zapisuje sie dokladnie iles tam rekordow a nie duble. Exceptiony itp.

Moj wniosek jest taki:

  • dla developmentu in memory db typu h2
  • przed produkcja jenkins stestuje np. Nightly buildami na wersji bazy jak na produkcji

Pozostało 580 znaków

2016-07-30 10:30
Krzywy Mariusz
0

Z testami integracyjnymi db tez potrafi byc taki problem, ze owywanie danych do testow potrafi byc slamazarne gdy chcemy przetestowac cos duzego.

Pozostało 580 znaków

2016-07-30 15:32
0

Przede wszystkim, testy jednostkowe odpala się na bieżąco, integracyjne tylko jeśli jednostkowe przejdą. Jeśli chodzi o wstawianie danych testowych, to może warto rozważyć przywracanie wejściowego stanu bazy z jakiegoś backupu, albo przy użyciu bulk insertów.
Jak dużo czasu zajmują te testy, że stanowi to problem?


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."

Pozostało 580 znaków

2016-07-30 16:15
Krzywy Mariusz
0

Jak developuje uzywajac tdd np. Nowego cruda to raczej na biezaco powstaja mi testy jednostkowe i integracyjne. To odpalam ten kawalek na biezaco.

Bywa tez tak, ze musze zmienic gdzies cos powiazanego. Wtedy chce puscic calosc calosc, zeby zobaczyc przy okazji czy jakies inne testy sie nie zaczely wywalac.

Mechanizmy do recreate bazy mam. Chodzi bardziej o to, ze bywa, ze mozolnie buduje jakies rulsy, ktore przygotowuja mi stan bazy do dalszych testow. Junity sa zawsze sa prostsze i bardziej odizolowane.

Pozostało 580 znaków

2016-07-30 19:31
0

Pisząc o "na bieżąco" miałem na myśli po każdym pushu do repozytorium. :)

Tak się zastanawiam, bo nigdy w sumie nie spotkałem się z tym, aby każdego CRUDa testować integracyjnie. Nie mówię, że to źle, ale co w ten sposób tak naprawdę testujesz - swój kod czy ORMa?


"HUMAN BEINGS MAKE LIFE SO INTERESTING. DO YOU KNOW, THAT IN A UNIVERSE SO FULL OF WONDERS, THEY HAVE MANAGED TO INVENT BOREDOM."
Musisz testować i swój kod i ORMa, i systemu baz danych, który pod tym ORMem jest. Nie ma opcji żeby testować tylko jedno lub drugie, bo do prawidłowego działania są potrzebne obydwa. A ORMy i bazy danych zresztą też miewają błędy. Oracle i MS SQL też. Dlatego testowanie na fake'owej bazie danych ala H2 jest już słabe bo może nie wyłapać błędów wynikających z jakiś tam niuansów bazy danych produkcyjnej. - Krolik 2016-08-01 11:03
Ale każdego CRUDa? Rozumiem jakiś proces, który robi coś nietypowego, ale przy CRUDach wystarczy przetestować ograniczony zbiór operacji i typów danych, a nie każdy nowy przypadek, który jest identyczny z już istniejącymi. - somekind 2016-08-01 12:29

Pozostało 580 znaków

2016-07-31 09:42
Krzywy Mariusz
0

Chcę w ten sposób testować możliwą całość. Czyli od requestu, po zapis i odczyt. Wtedy jest też dość bezpiecznie zmieniać cokolwiek. Bo szybki feedback jak się coś wywala. Tylko zaczyna się problem gdy tego przybywa, a jenkins zaczyna mielić wszystkie testy zanim wrzuci nam na instancje 'dev' ;)

Czasami naprawdę łatwo coś zepsuć przez przeoczenie. W javie np. ktoś źle pobawi się @Transactional, porobi coś dziwnego z hashcodes i equalsami i nagle mamy tonę nowych rekordów w bazie itp. Unit testy nie są w stanie tego zrobić. A używając Mockito to mam wrażenie, że niczego za bardzo nie sprawdzam, tylko raczej opisuję 'jak chcę by to działało' .
Różne bazy mają też specific syntax, więc np. w przypadku przenosin i mając jakieś queries popisane testy integracyjne wskażą mi miejsca do poprawy.

może też podrzucę linka
https://www.petrikainulainen.[...]ss-code-unit-tests-are-waste/

Pozostało 580 znaków

2016-08-01 10:37
4

Unit-testów używamy tam, gdzie API komponentu jest proste, a implementacja skomplikowana, ale niewymagająca zależności. Oczywiście dążymy do tego, aby interfejs każdego komponentu było prosty, niemniej niestety nie zawsze jest to możliwe. Przykładem takiego dobrego komponentu do testowania unit-testami byłoby np. malloc(). Interfejs prosty jak konstrukcja cepa, za to implementacja może być bardzo rozbudowana i nawet składać się z wielu prywatnych pod-komponentów (które zresztą też mogą mieć swoje unit-testy).

Z drugiej strony w systemach często są komponenty, których główną rolą jest pośredniczenie między innymi komponentami. Wszelkie proxy, adaptery, fasady, klasy DTO mapowane do bazy danych, itp. Takie komponenty nie mają same w sobie zbyt dużo logiki, za to mają bardzo dużo interakcji z resztą systemu, sklejają różne kawałki w całość i w związku z tym mają wiele zależności od innych komponentów lub wiele innych komponentów od nich zależy. Przykładem czegoś takiego może być np. handler Netty implementujący jakiś protokół, który dekoduje / przyjmuje żądania, konwertuje je i przesyła do innych komponentów, obsługuje wyjątki itp. Ale sam z siebie w sumie mało robi - głównie posługuje się innymi komponentami (inaczej musiałby być jakimś God-class). Co nie oznacza, że nie ma wcale kodu. Ba, może mieć bardzo dużo kodu, tyle że ten kod wygląda tak "weź ten obiekt A stąd i wyślij tam do B, a jak wróci w postaci C, to użyj komponentu D do przekonwertowania go na obiekt Z i wyślij go do Y". I jak to przetestować? Większość błędów jakie pojawiają się w tego typu komponentach wynika z nieprawidłowego użycia komponentów, z którymi takie "proxy" współpracuje. Np. nieprawidłowej kolejności wywołań, źle zainicjowanych argumentów, plików konfiguracyjnych w złym miejscu, niezrozumienia przez programistę semantyki pewnych operacji (niekoniecznie z winy programisty - czasami dokumentacja jest do d***, albo komponent robi co innego niż dokumentacja) itp.

Pisanie mocków do czegoś takiego to po pierwsze masakra, po drugie nie wychwyci błędów. Jak mockiem wyłapiesz, że np. wysyłasz błędne zapytanie? Jeszcze rozumiem, że zapytanie generujesz w wyniku jakiegoś złożonego procesu, ale jeśli wklepałeś je z palca w kodzie? To co taki test z mockiem Ci da? Jak wyłapiesz, czy zewnętrzny system faktycznie obsłuży to zapytanie i zwróci oczekiwane wyniki? Albo jak mockiem wyłapiesz, że nieprawidłowo zainicjowałeś jakiś tam framework i że np. plik konfiguracyjny jest w złym miejscu? Do takich rzeczy IMHO nadają się tylko testy integracyjne / funkcjonalne.

Wniosek: w dużym systemie zwykle będziesz potrzebował obu rodzajów testów. Jeśli system ma charakter integracyjny, to zapewne będziesz mieć przewagę testów integracyjnych. Jeśli system ma charakter bardziej obliczeniowy, algorytmiczny (np. AI do czegoś), to wtedy pewnie będziesz mieć więcej testów jednostkowych.

Ps. Całkowicie zgadzam się z treścią podlinkowanego artykułu. Unit testy są bez sensu do testowania kodu gadającego z bazą danych.

// dopisane:
A i jeszcze jedno: klienta nie będzie obchodzić, czy Twoje oprogramowanie wywali się z powodu błędu w Twoim kodzie, błędu użycia jakiejś biblioteki, czy z powodu błędu w samym frameworku/bibliotece, którego użyłeś. Powiadacie, że popularne frameworki i biblioteki nie mają błędów? Np. ORMy? Hahahahahaha. Kiedy robiłem szkolenia z Hibernate, Hibernate był już jakieś 5-6 lat na rynku (i był must-have w niemal każdym projekcie Javowym obok Springa). Miał błędy, który kończyły się zwracaniem nieprawidłowych wyników, albo potrafił generować może i poprawne semantycznie zapytania, ale zabijające bazę np. złączeniem kartezjańskim. Powodzenia w wyłapywaniu takich rzeczy unit-testami.

Dlatego w systemie musisz mieć jakieś testy, który testują wszystkie warstwy, łącznie z bibliotekami i frameworkami. Wiem, że to kosztuje niemało, ale z tego akurat właśnie nie można zrezygnować bez ryzykowania jakością produktu. Z unit-testów za to można zrezygnować, bo integracyjne i tak powinny wszystko wyłapać. Jedyna wada posiadania tylko integracyjnych/funkcjonalnych testów jest taka, że pewne błędy unit-testy mogą wyłapać i zlokalizować znacznie wcześniej i szybciej, bo szybciej się wykonują (a zatem można je uruchamiać częściej) i mają mniejszy zasięg.

edytowany 7x, ostatnio: Krolik, 2016-08-01 11:01

Pozostało 580 znaków

2016-08-01 11:02
0

A nie możesz testów integracyjnych przenieść do jakiegoś CI, np. Jenkinsa i niech on je robi po commicie jak jednostkowe u ciebie przejdą?

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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