Jakie testy piszecie?

2

Witam,

W ramach pisania hobbystycznie nowego projektu zaczalem sie zastanawiac nad podejsciem do testowania. W internecie mozna znalezc wiele informacji na temat roznych rodzajow testow i o jakim by sie nie czytalo, wydawac by sie moglo ze wlasnie ten konkretny rodzaj jest najwazniejszy, "sluszny" itp. Ostatnio coraz czesciej spotykam sie z podejsciem aby testowac dany "feature", tj. w ramach jednego testu (ktory moze miec kilka iteracji z roznymi danymi wejsciowymi) zostaje pokryty caly workflow z tymze testem zwiazany. W pewnym sensie niweluje to potrzebe testow jednostkowych (a moze i nie?) jako ze poszczegolne jednostki zostaja pokryte przez ten test. Czy Wy stosujecie takie testy (prywatnie lub w pracy)? A moze cos calkowicie innego?

Tutaj tez pojawia sie pytanie- czy np. testujac jakis kolejny modul API, np. zwrajacy liste zamowien, testujecie taki modul bezposrednio go wywolujac jak metode (np. wywolujac akcje kontrolera w ASP Web API) czy tez stawiacie testowy host, a wiec przy okazji testujecie takie elementy jak naglowki requestow?

Linki do ciekawych materialow mile widziane.

Pozdrawiam i zapraszam do dyskusji.

7
Aventus napisał(a):

Ostatnio coraz czesciej spotykam sie z podejsciem aby testowac dany "feature", tj. w ramach jednego testu (ktory moze miec kilka iteracji z roznymi danymi wejsciowymi) zostaje pokryty caly workflow z tymze testem zwiazany. W pewnym sensie niweluje to potrzebe testow jednostkowych (a moze i nie?) jako ze poszczegolne jednostki zostaja pokryte przez ten test. Czy Wy stosujecie takie testy (prywatnie lub w pracy)? A moze cos calkowicie innego?

Ja tak robię od zawsze i nazywam to testem jednostkowym. W ten sposób testuję jednostkę, czyli taką część kodu, która daje jakąś wartość. Nie testuję każdej klasy oddzielnie, bo to po prostu bezdennie głupia strata czasu.

Tutaj tez pojawia sie pytanie- czy np. testujac jakis kolejny modul API, np. zwrajacy liste zamowien, testujecie taki modul bezposrednio go wywolujac jak metode (np. wywolujac akcje kontrolera w ASP Web API) czy tez stawiacie testowy host, a wiec przy okazji testujecie takie elementy jak naglowki requestow?

Jeśli testuję endpoint na postawionym serwerze, to jest to dla mnie już test integracyjny, a nie jednostkowy. I takie testy też stosuje (a w niektórych przypadkach przede wszystkim takie), bo to jedyna możliwość faktycznego sprawdzenia, czy aplikacja działa. Bo co z tego, że testy jednostkowe pokażą, że logika przetwarzania danych jest prawidłowo zaimplementowana, skoro binding HTTP nie parsuje daty, albo pobierana jest wartość ze złego headera?

0
somekind napisał(a):

Jeśli testuję endpoint na postawionym serwerze, to jest to dla mnie już test integracyjny, a nie jednostkowy.

Dla wyjasnienia, chodzi mi to testowanie endpointa w pamieci, np. https://www.nuget.org/packages/Microsoft.AspNetCore.TestHost

0

Z tego, co rozumiem z opisu, to to nie jest w pamięci tylko po prostu lekki serwer aplikacji.

1

Nie trzeba stawiać serwera (tzn czegoś nasłuchującego na porcie) by przetestować końcówki RESTowe (wliczając w to parsowanie parametrów, nagłówków itd). Ciekawych odsyłam do dokumentacji Akki HTTP: https://doc.akka.io/docs/akka-http/current/routing-dsl/testkit.html

1

Nie lubię absurdalnych podziałów na różne rodzaje testów.
Test to test: dla danego wejścia sprawdzamy wyjście.

Nieważne czy to a) metoda typu 2+2 , b) czy też system do rozpatrywania kredytów, gdzie sprawdzamy, że jeżeli zarejestrowany wniosek kredytowy nie zostanie rozpatrzony w 2 tygodnie to trafia na czerwono na top listy do kierownika.
Mimo, ze maszyneria w przypadku b) jest bardziej skomplikowana, to ten test jest zupełnie normalnie postaci given - when - then (*). Oczywiście, żeby coś takiego utrzymać trzeba troszkę zainwestować.

Testowanie RESTów, tak jak pisze wyżej @Wibowit - w większości przypadków kluczowe elementy, łącznie z nagłówkami itp. sprawdzimy startując wirtualne endpointy (co ma tą zaletę, że nie trzeba bindować portu fizycznego i można odpalać wiele równolegle na jednej maszynie). Zupełnie fajnie jak można łatwo się przełączyć między testowaniem na fizycznym i wirtualnym porcie.

Tak zwaną integrację - np, czy system podniósł się na serwerze i czy działa z korpo baza danych i czy zbiera dane z jakiegoś innego systemu załatwiam przez smoke testy - mam ich malo. Czasem to selenium, czasem rest serwis diagnostyczny. (Często takie testy to objaw słabej infrastuktury, ale taka jest korporzeczywistość.)

* - kiedyś ze względów wydajnościowych bawiłem sie w stawianie baz testowych dla wszystkich testów, automatyczne rollbacki po każdym teście itp. W ostatnich latach odpalenie h2 z dumpa jest na tyle szybkie, że przeważnie można sobie całość podnosić i kłaść pro test. O wiele gorzej jest z czasem inicjowaniem kontektu springowego, który to jest np. w Springu nadal żenujący (nawet w Spring 5 webflux nie jest super - a tam kontektu nawet nie potrzebuje).

0

Nie lubię absurdalnych podziałów na różne rodzaje testów.

Ja mam wrażenie, że te podziały albo:

  1. stosują zwykle początkujący, którzy szukają punktu zaczepiania (tudzież autorzy kursów/podręczników, którzy szukają trafnej metafory dzielącą wiedzę na kilka obszarów, stąd mamy podział na e2e, integracyjne, unitowe). Czyli generalnie taki podział, który się stosuje w celach edukacyjnych.

  2. ludzie nieco bardziej zaawansowani stosują głównie po to, żeby z mądrą miną oddzielać rodzaj testów oraz po to, żeby trollować innych programistów i się kłócić z nimi o rodzaj testu (trochę jak w każdej dyskusji o Reakcie jako frameworku JS musi znaleźć się "this guy", który wyskoczy i powie React to nie framework bo mu XKCD 386 kazało, tak samo zawsze ktoś się będzie kłócił o to, jakiego rodzaju jest dany test.

Ew.
3. stosują ludzie, którzy po prostu potrzebują testować system na wielu poziomach, żeby sprawdzić poprawność działania aplikacji, dlatego roboczo wydzielają różne rodzaje testów, być może nawet stosują różne narzędzia (frameworki testowe, test runnery, headless browsers etc.) do testowania różnych rzeczy. Zapewne też trochę inną taktykę podejmują w przypadku różnych testów. Dlatego taki roboczy podział ma wtedy sens.

Co do 1. to Nie byłoby w tym nic złego, gdyby nie to, że złe rozumienie testów unitowych (czyli: piszemy testy do każdej klasy i metody) i rozpowszechniona opinia, że unit testy są "lepsze", prowadzi do pisania ogromnej ilości testów, które raz, że testują szczegóły implementacyjne (więc się rozwalą przy pierwszym refaktorze), dwa, że są kompletną stratą czasu, bo asercje są tak szczegółowe, że i tak nie powiedzą, czy apka działa, a jedynie to, czy implementacja pozostała taka sama.

To, co wielu ludzi uważa za testy unitowe, to raczej określa się snapshot tests (które nawiasem mówiąc można sobie wygenerować z automatu, jak ktoś chce - więc po co je pisać dodatkowo?).

A co do 2. to już jest przypadłość programistów (również moja), że coś nam każe mieć rację albo prostować to, co uważamy za błędy. Duty calls.

Punkt 3. niby oczywistość, ale mam wrażenie, że o testach więcej się mówi niż faktycznie się je pisze. A jeśli się je pisze to też ze złych powodów - z chęci bycia "profesjonalnym" albo z ambicji zdobycia 100% pokrycia kodu (co jest banalne do osiągnięcia swoją drogą), a nie z chęci przetestowania czy aplikacja dobrze działa i zapobieganiu regresji.

0
jarekr000000 napisał(a):

Tak zwaną integrację - np, czy system podniósł się na serwerze i czy działa z korpo baza danych i czy zbiera dane z jakiegoś innego systemu załatwiam przez smoke testy - mam ich malo.

@jarekr000000: Jak mało? Kilka na aplikację, czy raczej kilka na endpoint?

2

ludzie, którzy po prostu potrzebują testować system na wielu poziomach, żeby sprawdzić poprawność działania aplikacji, dlatego roboczo wydzielają różne rodzaje testów, być może nawet stosują różne narzędzia (frameworki testowe, test runnery, headless browsers etc.) do testowania różnych rzeczy. Zapewne też trochę inną taktykę podejmują w przypadku różnych testów. Dlatego taki roboczy podział ma wtedy sens.

Dokładnie. To normalne, że testuje się na różnych poziomach. I czasem ze względów technicznych te testy są robione w różnych technologiach. Aczkolwiek nie warto dopisywać do tego przesadnej ideologii nazewniczej. Już dwa razy widziałem zespoły dumne z posiadania wielu testów integracyjnych, gdzie de fakto testy integracyjne to były testy czy kontekst Springowy lub JavaEE faktycznie wstanie na serwerze. Przy kilku mgabajtach kodu w XMLu i drugim tyle adnotacjach niczego nie można być pewnym. Nawet jak wszystkie unit testy przejdą.

1

Testuje teraz podejscie takie, że do testów stawiam cały system ale w pamięci (zamiast bazy danych hashmapa itp) ale bez endpointów, samą część z logiką i testuje wszystkie metody publiczne w klasach publicznych jakie mam (czy metody fasad modułów). Dzięki temu nie muszę się bawić w żadne mocki ani nic bo wszystko działa na żywych obiektach. Minusem jest to, że potrzebuje coś w stylu bieda-sprigcontextu gdzie sam ręcznie składam cały system

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