Testy jednostkowe - co dla Was jest jednostką

0

Od razu przyznam, że jestem noobem jeśli chodzi o testy jednostkowe. Nigdy nie miałem szczęścia być w projekcie, gdzie testy były zrobione z głową - zazwyczaj albo ich nie było albo każdy pisał jak uważał. Zazwyczaj były to testy pisane w ten sposób, że testujemy klasę X a wszystkie zależności to mock. Czyli generalnie każda klasa ma (bądź powinna mieć) swój test. Takie podejście jest też wspierane przez IDE, które potrafi dzisiaj wygenerować stub dla testu umieszczając go w miejscu odzwierciedlającym miejsce w strukturze katalogów testowanej klasy.

Szczerze mówiąc wydawało mi się to zawsze... głupie. Refactoring większego systemu to katorga bo zmienisz jakąś poboczną klasę i nagle testy się sypią bo nie zmieniłeś mocków itp. Pisanie testów dla wszystkich klas wydaje się tez często overkillem, gdy klasę można dość łatwo i sprawnie przetestować pośrednio... No ale przecież to Unit Test, więc nie testujemy systemu tylko daną klasę... No właśnie czy tak jest?

Ostatnio sporo czytam o różnych zagadnieniach aby zobaczyć czym żyje świat i trafiłem między innymi na ciekawą książkę "Unit Testing Principles, Practices, and Patterns", która przedstawia wszystko trochę inaczej. Ogólnie (trochę uproszczę, bo trudno opisać całą filozofię w 5 punktach i przy okazji pewnie coś przekręcę):

  • powinniśmy unikać mocków dla wszystkiego co odbywa się w naszej aplikacji (domenie)
  • mocki stosujemy tylko do rzeczy typu baza, api etc - ewentualnie może do czegoś gdzie inaczej musielibyśmy stworzyć jakiś potężny graf zależności - tu jednak znowu to raczej problemem jest nasz kod, który te grafy zależności rozdmuchuje.
  • im więcej naszego kodu domenowego wywołuje test poprzez zależności tym lepiej, bo dzięki temu wyłapiemy więcej błędów
  • test, który pośrednio wywoła dużą ilość kodu spoza testowanej klasy nadal jest testem jednostkowym - nikt w końcu nie powiedział, że jednostką jest klasa
  • według autora w testach jednostkowych bardziej trzeba się skupić na jednostce "zachowania" niż jakiejś sztuczniej wydzielonej jednostce kodu (np. funkcji, klasy)

Powiem szczerze, że bardzo to do mnie trafiło i przywróciło chęć do pisania testów. Teraz testów piszę znacznie mniej, bo wiele klas testuję po prostu pośrednio, zwłaszcza takich, które nie mają rozbudowanej logiki biznesowej i mają mało powodów do zmiany. Bardzo zgrało się to z moim zmienionym podejściem do samego programowania, gdzie staram się rozdzielać domenę od reszty kodu i testuję głównie właśnie domenę. Mam wrażenie, że takie testy znacznie lepiej spełniają swoją rolę i do tego są o wiele mniej podatne na efekty uboczne przy refaktoringu. Ogólnie autor bardzo trafnie wypunktował moim zdaniem wiele patologii Unit Testów, które mnie męczyły.

Oczywiście jak klasa ma jakąś rozbudowaną logikę to piszę do niej testy szczegółowe mimo tego, że jest testowana pośrednio przez inne testy to jednak test szczegółowy też się przydaje, ale teraz jestem zdania, jak autor przytoczonej przeze mnie książki, że mocki to zło w 9 na 10 przypadków. Póki nie zahaczam o coś poza domeną (np. ORM czy na przykład system kolejkowy) to nawet test, który przeora połowę domeny traktuję jako jednostkowy.

Jak to wygląda u Was?

4

Pisałem o tym tutaj i tutaj, a ostatnio tutaj

Nie wiem po co jakieś książki, skoro jestem ja.

0

Podziel sobie ładnie na klasy, zrób tak aby się wydawało, że wszystko działa, odpal pitest i spraw aby pokrycie mutacjami było przynajmniej 70-80%.

3

Jednostką jest coś co ma testowalną logikę biznesową. Niestety testowanie klas, a w praktyce mockito jest dosyć częstym standardem i dążenie do pokrycia np. 90%, z czego jakieś 80% nie ma najmniejszego sensu.

0

Stosowaliśmy i działa

0

Ja piszę jedne i drugie. TEsty na poziomie klasy są głównie dla mnie, bo szybciej napisać parę linijek testu i sprawdzić klasę / metodę w ten sposób, niż wracać do niej dopiero jak walną testy na poziomie modułu.

0

jak ktoś coś zjebie, to ma być na czerwono

jak? irrelewantne

3

Podobne tematy przewijały się na forum już kilkukrotnie. Ja sam nie raz się wypowiadałem na ten temat, np. tutaj. Tak więc zastrzegam od razu że o ile w moim przypadku testy jednostkowe są ograniczone, to nie znaczy że za resztę odpowiadają testy integracyjne. Ja jestem zwolennikiem opierania większości testów na rozwiązaniu pośrednim (wyjaśnione chociażby w podlinkowanym poście).

Dobrzy kandydaci na testy jednostkowe to moim zdaniem:

  • Parsery, np. funkcja parsujaca jakiś klucz na enum/rekord
  • Funkcje mapujące, np. z obiektu domenowego na DTO
  • Proste serwisy bez skomplikowanych zależności, np. jakiś generator tokena na podstawie jakichś danych wejściowych
  • Jakieś serwisy walidujące zasady biznesowe dla danych wejściowych, np. serwis który musi przyjąć ryzyko ubezpieczeniowe i przepuścić przez kilka "zasad" zwracając wynik czy dane ryzyko jest akceptowalne czy też nie

Ogólnie jednostkami w takim przypadku są najczęściej funkcje o bardzo ograniczonym zadaniu i z minimalną ilością zależności (o ile w ogóle).

W przypadku aplikacji UI to oczywiście testy komponentów UI oraz funkcji pomocniczych, np. selectorów.

2

to jest ciekawa prezentacja na taki temat.

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