Sens testów automatycznych w jednoosobowym projekcie?

0

Jaki jest sens testów automatycznych? Jeśli się nie mylę, przede wszystkim chodzi o walkę z regresjami.

Scenariusz, przed którym się bronimy, wygląda mnie więcej tak:

  • Programista A pisze kod i czyni jakieś założenia odnośnie interfejsu, które spełnia kod w innej części aplikacji. Względnie natknął się na nieoczywisty przypadek graniczny i robi coś nieoczywistego w kodzie, by ten przypadek obsłużyć.
  • Rok później programista B nie zna założeń poczynionych przez progr. A ani nie jest w stanie przewidzieć tego samego przypadku granicznego, ale musi zmienić coś w tym kodzie. Więc łamie założenia i wpada w ten właśnie przypadek graniczny i o tym nie wie.
  • Mamy regresję.

Podczas gdy gdyby kod był dokładnie przetestowany - z naciskiem na to, co nieoczywiste - poleciałyby testy i regresji by nie było.

Jakie to ma zastosowanie dla osobistych projektów?

  • Szansa na tego rodzaju sytuację jest mniejsza, bo zakładamy, że programista w miarę ogarnia własny kod i mniej więcej pamięta, co dlaczego robił (a jeśli nie pamięta, to powinien potrafić sobie przypomnieć, gdy patrzy na dziwny kod)
  • Pisanie testów zabiera czas. Dwukrotność czasu na pisanie kodu? Strzelam, że coś koło tego. Mnie pewnie jeszcze więcej, bo nie mam w tym prawie żadnego doświadczenia.
  • Kiedyś tam próbowałem zrobić własną grę. Nie miała testów. Tak, zdarzało mi się wprowadzać regresje. Ale usuwałem je zazwyczaj szybko. I wykrywałem szybko, gdyż - co może być specyfiką gier - z testami, czy bez testów i tak trzeba ją uruchamiać co chwila.

Ale może ja się mylę? Może nawet w osobistych projektach testy są bardzo ważne, bo bez testów okazuje się, że po tygodniu - najdalej miesiącu - pracuję wolniej, niż z testami, tylko że o tym nie wiem, bo nigdy nie próbowałem? Wszak tyle osób naciska, że testy muszą być i że jest to absolutna podstawa. Zdarzało się, że na forach opensourcowych gierek widziałem ludków, którzy przychodzili tam po to, by pytać "dlaczego kod nie ma testów".

Ciekawa rzecz: pytałem o to na różnych serwerach Discordowych. Gamedevowym, C#-powym. Co bardzo mnie zdziwiło, odpowiedzi były nieco inne. Ktoś z etykietką "Verified Microsoft Employee" twierdził, że testy dla projektów osobistych to strata czasu. Wymaga to rozeznania, bo zależy od rodzaju projektów. Oni w MS mają dużo testów, bo w ich przypadku jest to istotne, i - tu żebym nie skłamał, może pamięć mnie pyli - w ogólności każdy projekt wykorzystywany jako zależność innego projektu powinien mieć testy, ale dla gier jest to już mniej ważne. Także sceptycznie na temat testów wypowiadał się na forum gamedevowym ktoś z etykietką "AA", wg niego testy to jest "no silver bullet".

Więc może jednak nie jest tak, jak by chcieli niektórzy, że testy muszą być zawsze, że są warunkiem wstępnym, by w ogóle chcieć patrzyć na kod? Czym innym jest kod, który w razie błędu zabija ludzi albo kosztuje górę forsy (Therac-25, Ariane 5, ...), taki kod musi być przetestowany bardzo dokładnie, o ile w ogóle jego poprawność nie powinna być dowiedziona matematycznie. Ale nie każdy soft jest taki.

Nie zmienia to faktu, że mój następny projekt osobisty chyba będzie zawierał testy. Nie po to, że są potrzebne, ale po to, bym nauczył się je pisać. Ale czy to nie cargo cult z kolei?

4
YetAnohterone napisał(a):

Nie zmienia to faktu, że mój następny projekt osobisty chyba będzie zawierał testy. Nie po to, że są potrzebne, ale po to, bym nauczył się je pisać. Ale czy to nie cargo cult z kolei?

Robienie czegokolwiek co nie jest potrzebne, tylko dlatego, że tak się robi, to cargo cult. Może w tym przypadku akurat to potrzebą jest nauka, ale gdybyś testy pisać umiał, a ich nie potrzebował to jaki to ma sens?

YetAnohterone napisał(a):
  • Kiedyś tam próbowałem zrobić własną grę. Nie miała testów. Tak, zdarzało mi się wprowadzać regresje. Ale usuwałem je zazwyczaj szybko. I wykrywałem szybko, gdyż - co może być specyfiką gier - z testami, czy bez testów i tak trzeba ją uruchamiać co chwila.

Ale skąd wiesz, że nie masz regresji, jeśli nie masz testów? Po drugie prawdziwą startą czasu jest ciągłe uruchamianie, nie po to człowiek się uczy programować, żeby klikał po programach jak małpa. Dwukrotny koszt napisania testów zwraca się już po jednokrotnym, konkretnym przeklikaniu przez aplikację.

Już nie wspominając o TDD i o tym, że testy zmuszają do pisania lepszego kodu, bo jak dostajesz raka pisząc testy do własnego kodu to znaczy, że jest z nim coś nie tak.

6

Sens testów automatycznych w jednoosobowym projekcie?

Bo lubie wiedzieć czy czegoś właśnie nie zepsułem. Puszczam testy i już wiem czy wszystko nadal działa. Szczególnie kiedy wymagania do projektu przychodzą "z zewnątrz" i mogą być niespójne/sprzeczne ze sobą. Implementujesz nowy ficzer i okazuje się że przy okazji psuje to jakiś istniejący o którym dawno zapomniałeś.

zakładamy, że programista w miarę ogarnia własny kod i mniej więcej pamięta, co dlaczego robił

Śmiałe zalożenie :D Obawiam sie ze jednak dość złudne, bo nie jesteś w stanie ogarnąć w taki sposób czegokolwiek większego.

Ale usuwałem je zazwyczaj szybko. I wykrywałem szybko, gdyż - co może być specyfiką gier - z testami, czy bez testów i tak trzeba ją uruchamiać co chwila.

No tak, czyli zamiast automatycznych testów lecących kilka sekund, musisz odpalać i testować manualnie :) Nie znam specyfiki gier ale twierdzenie że trzeba uruchamiać wydaje się mało realistyczne. Ty musisz uruchamiać bo nie masz jak inaczej przetestować ;) Szczególnie kiedy chodzi o testowanie jakiejś logiki domenowej, a nie tego czy shader ci zadziałał (bo to pewnie byłoby ciężko zautomatyzować).

1
YetAnohterone napisał(a):
  • Pisanie testów zabiera czas. Dwukrotność czasu na pisanie kodu? Strzelam, że coś koło tego. Mnie pewnie jeszcze więcej, bo nie mam w tym prawie żadnego doświadczenia.

Odpowiedź jak zwykle nie jest łatwa. Oczywiście, że pisanie testów zabiera czas ale to nie jest stratą czasu.
Bo kod testować trzeba więc albo piszesz testy albo robisz to inaczej. Nie można z tego zrezygnować. Ja robię inaczej ale ten czas na testowanie poświęcam.

Trzeba także wiedzieć, że:

  1. Cała technologia wspierająca automatyczne testy nie powstała bez powodu i jakby nie patrzeć w obszarach programowania gdzie jest to popularne spełnia swoje zadanie.
  2. Nie do każdego kodu da się napisać testy ( znaczy da się do każdego ale są przypadki, kiedy będzie to zwyczajnie głupie i nieuzasadnione ).
  3. Testy są na tyle skuteczne na ile skuteczne są funkcje testujące. Niestety to jest ich duży minus. Chronią nas tylko przed ewidentnymi błędami ale wyjątków często nie wyłapiemy. Są jedynie weryfikacją czy nowa funkcja ogólnie spełnia swoje zadanie. Jak ktoś nie wie co robi to nawet dobrego testu nie napisze... Zatem w przypadku jakiejś "programistycznej łajzy" koło się zamyka.
  4. Testy do dobra rzecz w świecie Tasków, których realizacja polega na napisaniu jednej metody albo poprawieniu jednej funkcji. Czyli popularne CRUDy, praca w dużych zespołach itp...

Jak wyżej napisałem z testów nie korzystam. Wychowałem się bez nich i nauczyłem się porządnie testować kod przed wrzuceniem na produkcję. Nie klepię bezmyślnie, a przed rozpoczęciem pisania doskonale wiem co mam napisać. Tak z 80% czasu poświęcam na myślenie co i jak napisać a 20% na samo wklepanie kodu.
Ponad to do tego w większości przypadków, którymi się zajmuję funkcja testująca musiałaby być kopią funkcji testowanej - zatem sens mały.
To wszystko oczywiście też jest czasochłonne więc pewnie czasowo na jedno wychodzi czy bym testy pisał czy solidnie testował to co oddaję.

Choć sam raczej nigdy się testów używać nie będę to rozumiem młodsze pokolenie, które z testów korzysta i nawet piszą je tworząc samodzielne projekty.
Testy to jedynie narzędzie w osiągnięciu celu, którym jest kod z mniejszą ilością błędów i czy będziesz testował automatycznie czy ręcznie to i tak musisz to zrobić.

Ponad to wszystko co wyżej napisane testy mają dodatkowe znaczenie w świecie współczesnych programistów, którzy ze względu na swoje ego lub lenistwo, od testowania wykręcają się na każdy możliwy sposób często dostarczając "goownokod". Zatem dla takich typów testy powinny być obowiązkowe.
Prosty przykład.. Czas uruchomienia nowej wersji aplikacji, przekazania do działu testów po to żeby tam stwierdzili, że funkcja sumująca zawsze zwraca zero to ogromna strata czasu dla kilku osób.
W takiej sytuacji programista powinien solidnie obrywać nawet finansowo, a w takiej sytuacji testy można już chcieć pisać samemu. To przejaw odpowiedzialności. Ja akurat odpowiadam jedynie sam przed sobą ale kara wynikająca z popełnionych błędów zwykle jest o wiele dotkliwsza niż reprymenda od managera czy mniejsza premia na koniec miesiąca.

5

Jak najbardziej warto pisać testy do wszystkiego gdzie się da i ma to sens. Nie tylko ze względu na wyłapywanie regresji. Ja głównie doceniam możliwość uruchamiania danego kawałku kodu w izolacji, bez potrzeby uruchamiania całej aplikacji, co jest znacznie wolniejsze. Testy są też dobrym papierkiem lakmusowym jakości kodu, im gorszy kod, tym ciężej będzie go przetestować.

Gier nie testuje się automatycznie tak dokładnie jak innych aplikacji komercyjnych, to jest prawda. Ale tylko dlatego, że gry to w głównej mierze geometria/grafika, i to na dodatek 3D. Bardzo ciężko się pisze testy do geometrii, powyżej jednego wymiaru.

4

Osobiście nie widzę różnicy między projektem komercyjnym a osobistym pod tym względem, no może poza tym, ze projekty osobiste mam zazwyczaj sensowniej przetestowane. Czas spędzony na testach jest wielokrotnie krótszy niż czas spędzony na debugowaniu.
A jak się ma pełne pokrycie integracyjnymi/E2E, to można wszystko praktycznie przepisać na nowo i mieć pewność, że dalej działa jak działało.

3

W jednoosobowym projekcie testy warto robic dla praktyki, nigdy nie wiesz kiedy zatrudnisz sie do firmy gdzie jest wiecej osob. a ze kazdy traktuje test po macoszemu, ty sie wyroznisz. Ja tez pisze sobie testy unit, czy feature testy i jak zmieniam kod to fajnie widziec na zielono same pass-y i daje to satysfakcje. Na szczescie gdy zaczynasz projekt to mozesz pisac testy zanim zaczniesz tworzyc projekt i kod. to wtedy jest najlepiej

1

W przypadku gier nie uniknę ręcznego uruchamiania tej gry i tak. Tu nawet nie chodzi o to, że shadera czy innej geometrii nie za bardzo jest jak przetestować automatycznie. Tu chodzi o to, że ja muszę wiedzieć, czy nowa mechanika, jaką zaimplementowałem, czyni grę dla mnie fajniejszą, czy mniej fajną. Jeśli gra dla mnie nie jest fajna, to nie będzie fajna tym bardziej dla tych, którzy mają w nią grać.

Gier nie da się napisać w ten sposób, że się najpierw rozpisuje funkcjonalność, rozdziela zadania po zespole, każdy zamyka się w piwnicy na miesiąc i pracuje na swoim bez uruchamiania całości i na koniec wszystkie elementy systemu się zbiera do kupy i uruchamia. Tzn. da się tak napisać grę, tyle że potem nie będzie się dało w tę grę grać. O tym mówili mi nawet jeszcze na uczelni.

Jeśli więc testy automatyczne mają za zadanie zastąpić ręczne uruchamianie programu, a ja go i tak muszę uruchamiać ręcznie, to czy nie duplikuję pracy?

3
YetAnohterone napisał(a):

Jeśli więc testy automatyczne mają za zadanie zastąpić ręczne uruchamianie programu, a ja go i tak muszę uruchamiać ręcznie, to czy nie duplikuję pracy?

Testy automatycznie nie służą do mierzenia frajdy z gry, ale nawet w grze mogą pomóc w wielu jej aspektach. W końcu gdzieś tam są też dane, liczby, warunki i procesy. Można automatycznie przetestować chociażby to, czy nie da się umieścić więcej niż jednej broni w jednej ręce postaci, albo czy nie da się przekroczyć pojemności ekwipunku. Albo czy kolizje obiektów na płaszczyźnie/przestrzeni są prawidłowo wykrywane. I pewnie setki innych rzeczy.

5

Za pół roku nie będziesz pamiętać, co robi dany kawałek kodu i dlaczego nagle przestał działać :) nie ma znaczenia, że jesteś sam. Pisząc testy będziesz mieć pewność, że czegoś nie zepsułeś (oczywiście zakładając, ze masz na to test).

2

Piszesz jakąś aplikację do obsługi procesu biznesowego, który lata przez ileś tam serwerów, itp. Albo piszesz grę w której trzeba poświęcić godzinę, żeby dojść do miejsca, gdzie ma zadziałać twoja funkcjonalność w postaci:

int add(int a, int b) return a+b

Co będzie szybsze: napisanie testu sprawdzającego, czy właśnie napisany kawałek kodu robi to czego oczekujesz, czy poświęcenie dnia na builda, instalację/deployment i przeklikiwanie się przez 100 menu? Skąd będziesz miał pewność, że testy manualne (z natury black box) przeszły przez ten kawałek kodu, a nie że został przypadkowo zwrócony prawidłowy wynik, bo proces nawet nie wszedł w to miejsce, którego dotknąłeś?

Pisanie testów jednostkowych jest możliwe jedynie w momencie kiedy kod jest napisany przyzwoicie. Testy to papierek lakmusowy jakości kodu. Jeżeli ich nie piszesz, to z mojego doświadczenia, prędzej lub później kod zejdzie na psy. W jaki sposób utrzymasz jakość kodu, w jednoosobowym projekcie, jak nikt nie rzuci ci podczas review "ej, stary, kompletnie nie wiadomo co tu chciałeś zrobić i po co"?

Projekt się rozrasta, trzeba zrobić jakiś refaktor, rozbić jakąś klasę na części, albo wydzielić interface. Skąd będziesz wiedział jakie są efekty tych zmian?

2

Jak we wszystkim najlepiej policzyć bilans zysków i strat. Ostatecznie wybierasz rozwiązanie, które bardziej się opłaca. Jeżeli konsekwencje popełnienia błędu są niewielkie, jesteś w stanie szybko zrobić fix'a, ręczne testowanie nie trwa kilku godzin czy dni to nie pisałbym testów za wszelką cenę.
Im większa aplikacja, liczba programistów z którą się pracuje, złożoność aplikacji tym większy jest sens pisania testów.

2
YetAnohterone napisał(a):
  • Programista A pisze kod i czyni jakieś założenia odnośnie interfejsu, które spełnia kod w innej części aplikacji. Względnie natknął się na nieoczywisty przypadek graniczny i robi coś nieoczywistego w kodzie, by ten przypadek obsłużyć.
  • Rok później programista B nie zna założeń poczynionych przez progr. A ani nie jest w stanie przewidzieć tego samego przypadku granicznego, ale musi zmienić coś w tym kodzie. Więc łamie założenia i wpada w ten właśnie przypadek graniczny i o tym nie wie.
  • Mamy regresję.

Po roku programista A i programista B to może być ta sama osoba.

  • Pisanie testów zabiera czas. Dwukrotność czasu na pisanie kodu? Strzelam, że coś koło tego. Mnie pewnie jeszcze więcej, bo nie mam w tym prawie żadnego doświadczenia.

Napisanie testów do gotowego kodu to może być dwukrotność czasu, ale tu nie liczysz największego kosztu oprogramowania: badanie i naprawianie produkcyjnych bugów.
Tyle razy podczas pisania testów odkrywałem błędy we własnym kodzie, że nie ufam sobie, ani code review. Muszę mieć testy, aby być spokojny.

2

Ja piszę, bo jak poświęcam swój czas to tym bardziej go cenię i nie chce mi się marnowac co chwile na uruchamianie aplikacji. Jak korzystam z testcontainers to nawet testy integracyjne są calkiem sprawne, więc oszczędzam dużo czasu, o regresji to nawet nie wspomnę.

0
ArchitektSpaghetti napisał(a):
YetAnohterone napisał(a):
  • Programista A pisze kod i czyni jakieś założenia odnośnie interfejsu, które spełnia kod w innej części aplikacji. Względnie natknął się na nieoczywisty przypadek graniczny i robi coś nieoczywistego w kodzie, by ten przypadek obsłużyć.
  • Rok później programista B nie zna założeń poczynionych przez progr. A ani nie jest w stanie przewidzieć tego samego przypadku granicznego, ale musi zmienić coś w tym kodzie. Więc łamie założenia i wpada w ten właśnie przypadek graniczny i o tym nie wie.
  • Mamy regresję.

Po roku programista A i programista B to może być ta sama osoba.

Patrzę po roku w swój własny kod w hobbystycznym projekcie i zastanawiam się czemu to tak napisałem i czemu jest tak źle (chociaż odpowiedź znam :D ). I pierwsza moja myśl, żeby to zrefaktoryzować, bo przecież takiego kodu mieć nie można. Bez testów to bym już dawno to zaorał. Druga moja myśl czy testy na pewno działają i że będzie trzeba pod koniec sprawdzić to manualnie :P (Ale manualne sprawdzanie jest naprawdę rzadkie)

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