Jak testować? jednostkowo czy behawioralnie?

1

Biznes: gdy ktoś pobierze książkę to ma odkładać się w chmurze rekord z id tej książki, id użytkownika, ścieżką http i datą.

IT: gdy ktoś strzeli w endpoint pobierający książkę produkowane jest zdarzenie (event) o tym. Zdarzenie jest konsumowane w innym komponencie tej samej aplikacji. Przy konsumowaniu mapowane jest do odpowiedniego stanu i wysyłane do chmury.

opcja 1:
image

opcja 2:
image

Mam nadzieję, że da radę zrozumieć istotę problemu o który mi się rozchodzi.

7

Testować i tak, i tak. Oba typy testów wyłapują inne rzeczy, są odpalane w innym miejscu i zwykle zabierają inną ilość czasu.

1

I cząstka, i fala.
Ludzie zapominają, że nie cały kod to jakieś funkcje stricte biznesowe, które da się przetestować e2e. Moim ulubionym przykładem są statyczne utilsy - nie wyobrażam sobie, żeby ktoś wrzucił YetAnotherStringCommons.doSomethingWithString(string), który będzie używany w różnych częściach kodu bez testu jednostkowego do tego.

4

Po pierwsze ponarzekać. Terminologia w rodzajach testów to jest jakaś porażka :D Są testy jednostkowe, ale czy ktoś ma jakiś papier co to jest ta jednostka? Powszechnie uważa się że klasa (lub klasa z zależnościami), a co w językach nie mających klas? Nazwa behawioralnie też jest śliska bo każdy kod ma zachowanie a prawie każde testy badają jakieś zachowanie (może za wyjątkiem testów wydajnościowych któe badają szybkość zachowania)
Chociaż w tym przykładzie to widzę że autor wprowadził jakieś definicje więc nie jest tak źle :P

A teraz na temat :P Ja chciałbym żeby testy były jak największe i żeby testowały jaknajbardziej realny przykład. Oczywiście wadą takiego podejścia jest to że testy takie potrafią być powolne lub mało stabilne (jak zależą od rzeczy których nie kontrolujemy). Dlatego potrzebujemy czasem mocków. Z drugiej strony test który przechodzi przez 300 klas (w Haskellu modułów), ale tylko jedna jest zamockowana to jest behawioralny czy jednostkowy?

Z drugiej strony jest czasem jakiś bardzo specyficzny (trudny) fragment. Czasem są to utilsy jak pisze @wartek01, czasem jakaś pokręcona logika biznesowa którą można przetestować niezależnie. Przykład z hobbystycznego projektu - na wejściu wpada liczba a na wyjściu ma być string-liczba w systemie siódemkowym (mam też konwersję odwrotną). No nie ma potrzeby pisać wielkiech testów stawiających całą aplikację żeby przetestować taki koder/dekoder

4
KamilAdam napisał(a):

Po pierwsze ponarzekać. Terminologia w rodzajach testów to jest jakaś porażka :D Są testy jednostkowe, ale czy ktoś ma jakiś papier co to jest ta jednostka?

Kiedyś powiedziałem rekruterującemu (senior developerowi), że można dyskutować nad tym, gdzie kończy się test jednostkowy, a zaczyna integracyjny. Odpowiedział prawie bez wahania, że test jednostkowy to jest test testujący 1 klasę. Po tym wiedziałem już, że to nie jest senior, tylko się tak nazywa.

0

Testowanie na poziomie pojedyńczych komponentów:

  • czy masz 99% pewności, że design jest dobry? Pisząc testy zakładasz niejawnie, że ten kod ma dobrą formę i chcesz przetestować go niezależnie od reszty. Jeśli nie to jest duża szansa, że przy kolejnej zmianie trzeba będzie przepisać testy co mija się z celem
  • testy na poziome komponentu są trudniejsze do ogarnięcia, bo zależą od wewnętrznej architektury kodu i praktyk. Testy na poziomie endpointu może pisać/analizować nawet małpa, która nie wie co to OOP, AbstractBeanFactory czy Free Monady

Ja wolę testować całość. Jak test tego samego kawałka logi jest tak samo skomplikowany na poziomie całości jak i komponentu to nawet nie trzeba się zastanawiać. Jak nie to warto przemyśleć wspominane przeze mnie wady i dopiero wtedy zadecydować:

  • czy testowany kawałek kodu jest używany w wielu miejscach na raz? Np. serwis, który jest wystawiony jako HTTP i gRPC: w takim przypadku jest sens testować logikę z osobna, bo nie chcemy duplikować testów dla każdego protokołu
  • czy takie testowanie da nam jakieś benefity np. dużo krótszy czas, prostsze debugowanie, łatwiejsze pisanie testów
0

opcja 2, jak druga zona zawsze lepsza.

0

Jak mamy jakieś komponenty, które tworzą większy system i to ten system dostarcza wartość użytkownikowi, to trzeba testować jedno i drugie.

  • komponenty na poziomie kontraktu - dostał strzała, coś się pojawiło na kolejce, albo coś się pojawiło na kolejce, wziął wiadomość i ją prawidłowo przetworzył
  • system na poziomie behawioralnym - czy nadal robi to co powinien robić, ktoś zrobił przelew, czy pieniądze zeszły z jego konta, operacja pojawiła się w historii i czy to samo pojawiło się na koncie docelowym

Testy behawioralne są potrzebne, bo trzeba sprawdzić czy coś się znajdzie na produkcji, testy komponentów są potrzebne, bo rzadko kiedy do końca wiadomo jakie konfiguracje na tej produkcji się znajdą. Do tego test systemu jest czasochłonny - trzeba wszystko zdeployować, odpalić jakies nightly, które będą rzeźbić to godzinami.

2

Zacznij pisać testy przed kodem, naturalnie Ci wyjdzie testowanie większych komponentów. Potem dopisujesz jakieś testy dla pewności, wiec powstaje mix jednostkowych i integracyjnych/behawioralnych/akceptacyjnych.

5

Testy to testy. K!

screenshot-20220521211143.png

Wszelkie gówniane koncepcje typu "testy jednostkowe" należy tępić.

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