Jakie testy piszecie?

Odpowiedz Nowy wątek
2018-09-02 20:24
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.


Na każdy złożony problem istnieje rozwiązanie które jest proste, szybkie i błędne.

Pozostało 580 znaków

2018-09-04 11:19
4

Obecnie temat testów (szczególnie w architekturze mikrousługowej) jest na czasie i wiele osób/firm zastanawia się jak to robić dobrze. Dyskusja trwa i wygląda na to, że wszyscy idą w podobnym kierunku (linki poniżej). Osobiście uważam, że testowania każdej metody osobno jest zbyt szczegółowe, a testowanie tylko endpointów jest zbyt ogólne. Całkiem sensowne wydaje mi się traktowanie jako "jednostki" jakiegoś spójnego, biznesowego konceptu. Weźmy pod uwagę na przykład składanie zamówienia w sklepie. Taki proces składa się z kilku części: przyjmowanie zapytania REST, pobieranie produktów z bazy danych, sprawdzanie czy użytkownik w ogóle jest uprawniony do dokonania tego zamówienia (np. czy ma odpowiedni wiek czy pakiet VIP), wyliczanie całkowitej ceny, aplikowanie rabatów itp. W takim przypadku osobno testowałbym walidator, osobno aplikowanie rabatów, osobno wyliczanie ceny, itp. To byłyby moje testy jednostkowe. Takie rzeczy jak OrderRepository pewnie przetestowałbym z realną bazą danych, myślę, że można nazwać to testem integracyjnym. Zrobiłbym też kilka smoke testów, żeby sprawdzić czy wszystko razem dobrze działa (na postawionej aplikacji). Takie podejście z moją obecną wiedzą wydaje mi się w miarę sensowne.

Jeżeli chodzi o linki to udało mi się zgromadzić takie:

Świetnie powiedziane, dobre materiały. Jak masz jeszcze jakieś ciekawe linki to podeślij. - ._. 2018-09-04 15:11

Pozostało 580 znaków

2018-09-04 12:46
._.
0

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?

Testy przez http bardziej brzmią jak testy black box'a, czyli ETE.
Binding możesz przetestować jednostkowo.
Ja to robie tak: https://github.com/Ja-rek/CSh[...]indersTest/ItemsBinderTest.cs

Pozostało 580 znaków

2018-09-04 17:05
0
._. napisał(a):

Binding możesz przetestować jednostkowo.

Mogę też przetestować jednostkowo filtry, handlery i kontrolery. Tylko po?
Moim zdaniem sztuczny izolowany test komponentu ściśle zależnego od infrastruktury daje bardzo niewiele. To coś jak testowanie treści SQL generowanych przez ORM. Pewnie ma sens jeśli piszemy ORMa, a niekoniecznie gdy z niego korzystamy.

Co mi po przechodzących testach jednostkowych samego bindera, skoro endpoint nie będzie działał, bo ktoś tego bindera zwyczajnie nie użyje? Albo ktoś zrefaktoryzuje binder, poprawi testy, a potem okaże się, że w praktyce i tak źle binduje, bo w unit testach zapomniał o przypadku, że parametry geta mogą mieć prefiksy? A co jeśli w nowej wersji frameworka zajdą jakieś zmiany wewnętrzne i okaże się, że unit testy dla binderów są niekompatybilne z nową infrastrukturą? Może dojść do takiej pięknej sytuacji, że unit testy mogą się nawet przestać kompilować, a aplikacja będzie działać prawidłowo.
Niepisanie unit testów i skupienie się na dobrych testach integracyjnych przed tym zabezpiecza.


"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

2018-09-04 17:38
0

Podział testów powinien być na:

  • szybkie (aka jednostkowe)
  • wolne (aka integracyjne)
  • strasznie wolne (aka behawioralne/E2E)

I nie ma tak, że jakieś są ważniejsze od innych. Testy integracyjne są potrzebne z tego powodu co napisał @somekind, ale nie zgodzę się, że są one ważniejsze od jednostkowych. Jednostkowe są po to, by móc je odpalać często gęsto, w czasie developmentu, by móc stwierdzić na szybko czy zepsuliśmy założenia międzymordzia czy nie. Jak nam wszystko przejdzie to oczywiście należy odpalić testy integracyjne, by mieć pewność, że wszystko działa jak powinno, ale przecież nie będziesz odpalał integracji za każdym razem jak się zmieni pojedyncza linia w kodzie, bo nie robiłbyś nic innego, tylko czekał na wyniki testów.

Pozostało 580 znaków

2018-09-04 17:42
._.
0
somekind napisał(a):

Mogę też przetestować jednostkowo filtry, handlery i kontrolery. Tylko po?
Moim zdaniem sztuczny izolowany test komponentu ściśle zależnego od infrastruktury daje bardzo niewiele. To coś jak testowanie treści SQL generowanych przez ORM. Pewnie ma sens jeśli piszemy ORMa, a niekoniecznie gdy z niego korzystamy.

Co mi po przechodzących testach jednostkowych samego bindera, skoro endpoint nie będzie działał, bo ktoś tego bindera zwyczajnie nie użyje? Albo ktoś zrefaktoryzuje binder, poprawi testy, a potem okaże się, że w praktyce i tak źle binduje, bo w unit testach zapomniał o przypadku, że parametry geta mogą mieć prefiksy? A co jeśli w nowej wersji frameworka zajdą jakieś zmiany wewnętrzne i okaże się, że unit testy dla binderów są niekompatybilne z nową infrastrukturą? Może dojść do takiej pięknej sytuacji, że unit testy mogą się nawet przestać kompilować, a aplikacja będzie działać prawidłowo.
Niepisanie unit testów i skupienie się na dobrych testach integracyjnych przed tym zabezpiecza.

Tak masz racje, ja nie mówie że to są końcowe testy, które mówią ze aplikacja zachowuje się prawidłowo. Te testy mają zmniejszyć problem wielkiego wybuchu. Gdzie nagle wysypują się wyjątki i tak czy siak musisz używać debugera, bo musisz debugować test. A przecież nie o to chodzi. No nie wiem, czy będziesz miał okazje wymienić Infrę, która rysuje prezentacje. Jeśli już to każda powinna mieć inne testy. Oczywiście możesz te testy pominąć, ponieważ zwykle logika filtrów i tak dalej, nie jest zbyt skomplikowana, decyzja należy do ciebie.

edytowany 1x, ostatnio: ._., 2018-09-04 17:44

Pozostało 580 znaków

2018-09-06 06:24
1

Ostatnio piszę testy kompilacyjne. Jesli się kompiluje, znaczy, że działa. Taki test nie ma żadnej asercji lub asercje, które mogą zwrócić tylko true.

Np. wczoraj napisałem funkcję sprawdzającą jakiś warunek. Jeśli warunek jest spełniony, funkcja zwraca true. Jeśli nie jest, funkcja rzuca błędem kompilacji.

Testy kompilacyjne mają szereg zalet i kilka wad.
Zalety:

  • Czas wykonania testu = czas skompilowania
  • IDE pokazuje, czy kod jest poprawny, a więc, czy będzie działał, więc jeśli mamy zaufanie do IDE, to można nawet nie kompilować ;)
  • Kompilacja przyrostowa pozwala wykonywać tylko te testy, które faktycznie mogliśmy zepsuć ostatnią zmianą. W praktyce każda zmiana w projekcie, który teraz robię, "testuje" się typowo 2-5 sekund.
  • Można testować własności, które wymagałyby przetestowania nieskonczonej liczby przypadków w testowaniu tradycyjnym.

Wady:

  • Wielu rzeczy nie da się tak w praktyce przetestować, bo test mógłby być znacznie trudniejszy do napisania niż kod, który testuje.
  • Nie da się przetestować każdego kodu tą metodą.
  • Czas kompilacji testów może znacząco wzrosnąć, jeśli się nie jest uwaznym.
  • Podejście to wymaga języka z porządnym systemem typów i porządnym systemem metaprogramowania.. Np. Scala a jeszcze lepiej Idris. Mam wątpliwości, czy Haskell* się łapie.
  • Debugowanie wymaga możliwości podłączenia debuggera do kompilatora. Scala na JVM to umożliwia, ale nie wiem jak inne języki.

Oczywiście poza tymi testami mam też jednostkowe i integracyjne, bo udowadnianie statycznie pewnych własności dla wszystkich możliwych wejść jest znacznie trudniejsze niż napisanie testu jednostkowego i sprawdzenie kilku przypadków.

*) Haskell nie obsługuje typów zależnych oraz wymaga dodatkowych rozszerzeń do metaprogramowania.

edytowany 3x, ostatnio: Krolik, 2018-09-06 06:35
Pokaż pozostałe 5 komentarzy
O np. tak: def transform[In](obj: In): obj.Out = { ... } - Krolik 2018-09-06 15:34
Tu macie do poczytania, wprawdzie nie o Scali, ale chodzi o takie właśnie techniki: http://kevinmahoney.co.uk/articles/tests-vs-types/ - Krolik 2018-09-06 15:38
Czyli, w zasadzie, zakładając idealistyczny przypadek 100% pokrycia kodu i specyfikacji takimi testami, to te testy służyłyby za matematyczny dowód poprawności programu? - kmph 2018-09-06 23:36
Tak, jednak nie dla każdego poprawnego programu da się stworzyć dowód poprawności, a dla wielu będzie to niepraktyczne. Systemy typów mająa też pewne ograniczenia (Scala nie umie tyle co Idris, Haskell nie umie tyle co Scala, a Java czy C# to już prawie w ogóle nic nie umieją w te klocki), więc nie zawsze kompilator umie przeprowadzić dowód, który umialby zrobić człowiek. Dlatego używamy systemu typów tam gdzie jest to praktyczne, a normalnych testów czasu wykonania wszędzie indziej. - Krolik 2018-09-07 09:12
No i jeszcze dochodzi kwestia, że sam dowód poprawności może mieć błąd (analogicznie do testu z błędem). Np. nic nie stoi na przeszkodzie powiedzieć kompilatorowi w specyfikacji, że 2+2 jest 5, a on z tego może później wyciągnąć wnioski. - Krolik 2018-09-07 09:14

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