Skocz do zawartości
Komentator

Czym jest Test Driven Development? Wprowadzenie, przykłady

Pomocna odpowiedź

Czym jest Test Driven Development? Wprowadzenie, przykłady

Artykuł ten jest krótkim wprowadzeniem do Test Driven Development, dzięki któremu każdy może poznać podstawy i prześledzić przykłady pisania kodu zgodnie z tą techniką. TDD docenią szczególnie osoby, które mają już dosyć mozolnego szukania błędów w programie i chciałyby przejść na trochę wyższy poziom.

UWAGA, to tylko wstęp! Dalsza część artykułu dostępna jest na blogu.

Przeczytaj całość »

Poniżej znajdują się komentarze powiązane z tym wpisem.

Udostępnij ten post


Link to post
Share on other sites

Super, wychodzi na to że TDD to lekarstwo na wszystkie problemy trapiące programistów.

Stąd moje pytanie: a czy TDD ma jakieś wady? Przy okazji filmik z podpowiedzią (która moim zdaniem idealnie pasuje do przykładów z artykułu, które nawet nie zgłaszają przepełnienia, czy też odczytu z pustego bufora):

 

Udostępnij ten post


Link to post
Share on other sites

@Elvis wnioskuję po sposobie zadania pytania, że chyba jednak znasz (chociaż trochę) TDD i masz świadomość jego wad 😉 Może po prostu napisz jakie są według Ciebie największe wady, o których warto pamiętać. Takie podejście do tematu sprawi, że jest większa szansa na merytoryczną dyskusję w komentarzach, która będzie pomocna dla osób nieznających TDD, a chyba o to chodzi w przypadku takich publikacji. Jeśli źle zinterpretowałem charakter Twojej wypowiedzi to przepraszam, ale jednak coś mi się wydaję, że znasz ten temat na tyle, aby się konkretnie wypowiedzieć 😉

Udostępnij ten post


Link to post
Share on other sites

Podobno nie ma rzeczy idealnych, więc moje pytanie było - a co i kiedy w TDD jest złe? Ja nie jestem zbytnim entuzjastą takiego podejścia, więc wolałbym się nie wypowiadać. Może lepiej, żeby autor artykułu coś napisał - no chyba że jego zdaniem TDD jest receptą na wszystkie problemy.

A co do wklejonego filmiku, to pierwsza rzecz, na którą zwróciłem uwagę to brak obsługi błędów w prezentowanym kodzie. Wszystko fajnie, przechodzi testy jednostkowe, ale jeśli użyjemy takiego bufora w realnej aplikacji, odczyt z pustego bufora, albo zapis do pełnego nie będzie sygnalizowany. Takie zachowania kodu prowadzą do błędów, które ciężko jest wykryć, bo najczęściej w buforze są jakieś stare, ale często sensowne dane. Stąd ten filmik z całkiem poprawnym zamknięciem, ale zupełnie niedopasowanym do drzwi jakoś mi pasował...

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@Elvis dziękuję, myślę, że taka forma komentarza przyczyni się do tego, że autorowi artykułu będzie łatwiej udzielić merytorycznej odpowiedzi 😉

Udostępnij ten post


Link to post
Share on other sites

@Elvis przykład miał na celu pokazanie czytelnikowi zaczynającemu z TDD sposobu pracy, który jest zupełnie odmienny od standardowego podejścia. Napisałem kilka pierwszych testów i zaznaczyłem w tekście, że dopisanie pozostałych pozostawiam czytelnikom jako ćwiczenie. Konkretne nazwy testów do zrobienia nawet są wypisane w formie komentarza. Zawierają one z resztą dokładnie te przypadki, o których mówisz. Może faktycznie przydała by się wielka czerwona ramka mówiąca, że to nie jest jeszcze skończona implementacja i kodu w takiej formie nie należy kopiować do własnych projektów. Świadomie zrezygnowałem z łopatologicznego opisywania całej implementacji do końca, bo po tych pierwszych testach już cały schemat pracy się powtarza i nie ma sensu opisywać ciągle tego samego. Tym bardziej, że artykuł już był bardzo długi. Pewnie lepiej do prezentacji sprawdziłoby się wideo. Albo mogę w przykładzie na githubie dopisać pełną implementację zgodnie z TDD, żebyś nie oceniał niedokończonego kodu. Bo stosowanie TDD właśnie sprzyja myśleniu o błędach i prędzej w ten sposób zabezpieczysz się przed overflowami itp niż pisząc wszystko z palca.

A teraz co w TDD jest złe? Nic nie jest złe, po prostu TDD nie nadaje się do każdej sytuacji. Nie znajdziemy w ten sposób np. błędów ze współbieżnością, czy problemów performance'owych. Nie ma sensu robić TDD jeżeli eksperymentujemy z kodem i nie wiemy jeszcze co chcemy osiągnąć. Napisałem o tym cały artykuł:

https://ucgosu.pl/2017/09/kiedy-nie-stosowac-tdd/

Dlatego w dobrym projekcie powinno być też miejsce na inne poziomy testów i analizę statyczną. Natomiast w króciutkim programie na 100 linijek pisanym w jeden dzień faktycznie nie opłaca się stosować TDD (ani wielu innych przydatnych technik), bo więcej czasu stracimy na konfigurację niż na samo pisanie kodu. Natomiast ten artykuł nie miał analizować wszystkich aspektów TDD, tylko pokazać tryb pracy, w którym robimy małe iteracje test-implementacja zamiast siedzieć długi czas nad implementacją, a potem długi czas nad debugowaniem.

Często jako argument przeciw TDD podaje się, że tracimy w ten sposób dużo więcej czasu, a testy nic nie dają. Oba stwierdzenia nie są prawdziwe, bo po pierwsze tracimy podczas developmentu dużo czasu schodzi na debugowanie, którego potem nie możemy łatwo powtórzyć. A poza tym więcej bugów wraca do nas w późniejszych fazach projektu.

@Elvis skoro nie jesteś entuzjastą TDD to śmiało napisz jakie widzisz w nim problemy, może z tego powstać ciekawa dyskusja.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Ja uważam, że TDD to zupełne nieporozumienie, jak kiedyś XP i wiele innych modnych haseł, na które moda szczęśliwie przeminęła. Ale skoro masz opis kiedy nie stosować tdd oraz link do artykułu https://dhh.dk/2014/tdd-is-dead-long-live-testing.html to jak dla mnie temat jest omówiony. Jeśli ktoś chce stosować TDD, to fajnie, jak nie - to jeszcze lepiej.

Oczywiście nie jestem przeciwnikiem testowania oprogramowania, jedynie uważam, że stosowanie TDD oraz testów jednostkowych często więcej psuje niż pomaga 🙂

Edit: jeszcze link do nieco szerszego artykułu https://rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf (jest na końcu wspomnianego wcześniej tekstu)

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Prawda jest taka, że nie ma głopko-odpornych praktyk i metodologii — natura zawsze znajdzie większego głupka. Jakby ty wszystko było takie proste, że wystarczy przestrzegać krok po kroku ustalonych punktów, to już dawno byłoby to zautomatyzowane. Wiec oczywiście nie, testy w niczym nie pomogą jeśli nie potrafisz ich napisać.

Z drugiej strony przetestować swoje rozwiązanie musisz tak czy inaczej. Jak ci płacą od godziny i bawi cię robienie milion razy tej samej rzeczy, to rzeczywiście, automatyczne testy wszystko ci tylko psują. Ale jak budujesz w więcej niż 3 osoby coś, co ma więcej niż te 10k linii kodu i składa się z więcej niż 5 części, to życzę powodzenia przy testowaniu manualnym.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Właśnie dlatego w firmach gdzie jest więcej niż 3 osoby oraz kod się rozrasta zatrudniani są tak dziwni ludzie jak testerzy. Bo testy automatyczne, to tylko część całej opowieści, a przygotowanie nietrywialnego planu testów wymaga sporo czasu i umiejętności. Dlatego nie wszystko mogą i powinni robić programiści.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Ja stosuje TDD komercyjnie już od paru ładnych lat i widzę w nim ogromne korzyści. Co więcej walczyłem o wprowadzenie unit testów w różnych projektach, w których brałem udział i widziałem jak ludzie z czasem się do nich przekonywali. Jak zmieniała się ich ocena po tym jak testy wyłapały coś naprawdę grubego, co normalnie mogłoby kosztować wiele dni poszukiwań. Mam dużo doświadczeń pokazujących, że unit testy są przydatne, dlatego je polecam. Z resztą zdecydowana większość autorytetów programowania takich jak np. Uncle Bob, czy Martin Fowler też poleca TDD.

DHH w swoim artykule pisze, że już nie potrzebuje używać TDD bo wyłapał dobre nawyki przez lata, kiedy go stosował. Podejście bez testów może się sprawdzić w środowisku, gdzie kod piszę tylko jedna osoba, która ma duże doświadczenie. Natomiast jeżeli pracujesz w zespole, są tam nie tylko seniorzy, a system jest duży to musisz mieć feedback, czy coś zepsułeś w innym kodzie.

A z XP też poruszyłeś ciekawy temat, bo XP jako termin nie jest już praktycznie używane, ale większość stawianym w nich tez i zalecanych technik ma się bardzo dobrze. Żeby wymienić choćby TDD, Continuous Integration, Code Review, czy Refactoring.

 

  • Lubię! 2

Udostępnij ten post


Link to post
Share on other sites

@Elvis A też z trochę innej beczki - piszesz, że więcej psuje niż pomaga - możesz to jakoś uargumentować przypadkami? Argumenty za mamy wyjaśnione w artykule.

I też najważniejsze - czy pracowałeś wcześniej z testami/TDD? Zakładam, ze skoro masz wypracowane zdanie w tym temacie to "odpowiednio"(pojęcie względne) długo miałeś z nimi do czynienia i się u Ciebie zwyczajnie nie sprawdziły, tak?

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@dambo przeczytaj to artykuł podlinkowany z bloga @GAndaLF-a (https://rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdftam znajdziesz dokładnie to co ja myślę o testach jednostkowych. Same testy bywają bardzo przydatne, ale tylko do pewnych zastosowań. Natomiast TDD to zupełnie co innego - to ideologia, która jak wiele innych, z komunizmem na czele, dobrze wygląda i brzmi w dziełach ich twórców, ale niekoniecznie sprawdza się w życiu. A co do mojego doświadczenia, to pracowałem przy projektach gdzie wymagane było 100% pokrycia testami, pracowałem przy projektach gdzie było niecałe 100% ale kod się nie trzymał przysłowiowej "kupy", teraz pracuję przy projekcie, gdzie prawie pełne pokrycie testami zostało dodane w kolejnej wersji tego samego projektu. I tak jak napisałem wcześniej - co ma też @GAndaLF na swoim blogu : testy jednostkowe są super narzędziem, ale tylko do pewnych zastosowań. Testowanie wszystkiego jest zupełnie bez sensu i wprowadza istotne wady. Po pierwsze łamie dość ważną regułę DRY (Don't Repeat Yourself). Po drugie, w przypadku systemów wbudowanych dużo więcej poważnych problemów jest na styku oprogramowanie - sprzęt, niż w samej logice aplikacji. A moim zdaniem testy jednostkowe tylko do tego się nadają. Bo jak ktoś próbuje testować procedury obsługi przerwania używając testów, to nie tylko marnuje czas, ale i psuje projekt (niestety to przykład z autentycznego projektu).

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Chciałem to doprecyzować, bo bardzo dużo rzeczy napisałeś bardzo ogólnie.

Co do testerów - unit testy są na samym dole piramidy testów - i bardziej są dla deweloperów - szybki feedback, że to co napisali działa i jak w artykule było wspomniane pozwala na skrócenie czasu do znalezienia błędu. Testerzy powinni pracować na wyższych poziomach testów (na blogu Gandalfa też o tym jest).

Napisałeś, że kod nie trzymał się kupy - tylko i wyłącznie z tego powodu, że były tam testy? I też inna kwestia - czy były dobrze zaplanowane itp. Oczywiście jak już wspomniałeś - to może nie jest narzędzie idealne do wszystkiego - więc czy możesz tam jednoznacznie stwierdzić dlaczego akurat w tym projekcie się nie sprawdziło?

Co do łamania DRY - napiszesz coś więcej? Bo wstępnie z tym się nie zgodzę - po to są np "Test Fixtures", żeby kod testów też był przejrzyście napisany.

"Po drugie, w przypadku systemów wbudowanych dużo więcej poważnych problemów jest na styku oprogramowanie - sprzęt, niż w samej logice aplikacji. A moim zdaniem testy jednostkowe tylko do tego się nadają. Bo jak ktoś próbuje testować procedury obsługi przerwania używając testów, to nie tylko marnuje czas, ale i psuje projekt (niestety to przykład z autentycznego projektu)"

Dlatego zależności od sprzętu przy testach ucinamy/mockujemy, a testujemy logikę - czy to drivera, czy aplikacji itp. Jednak projekty nie składają się wyłącznie z driverów "nie do przetestowania" - więc trzeba wiedzieć co można przetestować, a co nie.

I też zależy co rozumiesz przez "testować procedury obsługi przerwania" - bo jeśli chodzi o samą logikę funkcji, która miałaby się wykonać w przerwaniu - nie widzę dlaczego nie można byłoby jej przetestować.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@dambo piszę ogólnie, bo mieszam kilka różnych przykładów. Zacznijmy od początku. Ja nie twierdzę, że testy jednostkowe są zawsze złe. One są bardzo dobrym narzędziem, albo raczej bywają. Trzeba wiedzieć kiedy je zastosować, a kiedy nie należy. Dlatego zadałem na początku dyskusji pytanie - kiedy takie podejście się nie sprawdza.

Jak chodzi o moje doświadczenie, to jest go całkiem sporo, więc byłoby chyba łatwiej wybrać kilka przykładów i omówić. Pierwsze co przychodzi mi do głowy to projekt dekodera tv (set-top-box). Sam system całkiem spory, oparty na linuksie, do tego paskudnych driverach od broadcom-a. W projekcie zaangażowane kilka różnych firm - kto inny wykonuje elektronikę, kto inny uruchamia system, nawet aplikacja użytkownika jest wykonywana w dwóch firmach, na dwóch różnych kontynentach. W każdym razie wymóg odnośnie fragmentu, przy którym pracowałem był taki że ma być 100% pokrycia unit testami (czyste C, więc wszystko dość paskudne no i stary dobry "check"). Ja w tym projekcie byłem tylko przez chwilę, jako konsultant i dostałem proste zadanie - dodać obsługę nowego pilota do tv. Zadanie na 5 min, bo sam driver był i tak dostarczony przez broadcoma... Skończyło się na 5 min zmiany i 2 dniach walki z testami jednostkowymi. Bo ktoś sobie wymyślił że zasymuluje zależności czasowe... a ten nowy pilot różnił się właśnie czasem. Więc zysk z testu absolutnie żaden, a roboty mnóstwo. I jeszcze jako morał - w końcu i tak trzeba było użyć innego pilota, bo tradycyjne na podczerwień słabo sobie radzą z szybkim naciskaniem przycisków (transmisja o ile pamiętam co 100ms).

Niestety to nie jest jedyna opowieść którą mogę przytoczyć - inna, fajna bo krótka. Pracowałem przy projekcie urządzenia z mikrokontrolerem STM32. Mieliśmy również 100% pokrycia testami, ale ponieważ był to C++ to było trochę łatwiej i ładniej. Całość była bardzo ładnie przygotowana, kod był kompilowany na PC używając visual studio, a dopiero ostateczna wersja kompilowana skrośnie używając Keil-a. Cała wastwa abstrakcji sprzętu została przepisana i pozwalała na uruchamianie porządnych testów bez użycia sprzętu. Było bardzo fajnie. No może poza tym że po miesiącu się okazało że kod już dawno nie mieści się w pamięci STM32 🙂

Albo bardzo stary przykład - nawigacja samochodowa, z obsługą modemu GSM (to bylo jeszcze przed LTE, a nawet 3G). Okazało się, że wszystko pięknie działa, ale jak testrzy pojechali za granicę i urządzenie przełączało się między roamingiem, a siecią bazową to gubiło połączenie i koniec. Ciekawe jak można na takie coś wpaść pisząc unit testy...

W kwestii łamania DRY proponuję poczytać podlinkowanego pdf-a, tam jest wszystko opisane. Z mojej strony dodam, że używanie unit testów jest bardzo czasochłonne i jakoś tak się składa, że każdy zespół programistów z którym pracowałem zaczyne ja dodawać do wszystkiego, czy to ma sens, czy nie. I szybko zamiast pisać kod, wszyscy piszą bezsensowne testy. A zmiany w kodzie zajmują kilka razy wiecej czasu niż powinny, bo trzeba naprawiać również te bezsensowne testy.

Ale jak napisałem wcześniej - czasem unit testy są przydatne, tego nie neguję. Tylko jak napisałem - moim zdaniem nie zawsze i nie wszędzie.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Super - dokładnie o taką odpowiedź "drążyłem" temat 🙂

Chociaż wydaje mi się - że pierwsze 2 przypadki są właśnie pokazem jak z czegoś co sam określiłeś "One są bardzo dobrym narzędziem, albo raczej bywają. Trzeba wiedzieć kiedy je zastosować, a kiedy nie należy" - tzn - czy w pierwszym przypadku ("Bo ktoś sobie wymyślił że zasymuluje zależności czasowe..)" ten ktoś powinien pomyśleć czy wjeżdzanie w aż takie zależności czasowe przy testach ma sens? Zapewne w systemie było wiele modułów przetestowanych, a podajesz jeden jako przykład, że się wcale to nie sprawdziło.

Przykład 3 - w założeniu testy nie wyłapią wszystkiego - więc taki wyjątek może się zawsze znaleźć - czyli cała reszta testów w projekcie była bez sensu?

Wszystko się sprowadza do tego - "jakoś tak się składa, że każdy zespół programistów z którym pracowałem zaczyne ja dodawać do wszystkiego, czy to ma sens, czy nie. I szybko zamiast pisać kod, wszyscy piszą bezsensowne testy." - czyli ktoś nad nimi podjął błędną decyzję co do testów/źle zaprojektowali architekturę itp. Jakąkolwiek technikę można obalić/stwierdzić, ze jest nieprzydatna/zła gdy się ją źle wykorzystuje. Wiadomo od czego jest gorsza nadgorliwość 🙂

A też jeśli mogę zadam inne pytanie - przedstawiłeś negatywne przykłady - a czy mógłbyś podzielić się też jakimiś pozytywnymi? Aczkolwiek z tym może być ciężko - bo z powodu krótszego feedbacku - szybciej dowiadujemy się o pomyłkach i jakoś nie przeradzają się potem w jakieś spektakularne. Więc też trochę inny przypadek - czy miałeś (i w jakich przypadkach) refleksje podczas jakiegoś projektu, że "gdyby były testy to ten błąd byśmy już dawno wyłapali"?

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Gość
Dołącz do dyskusji! Kliknij, aby zacząć pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...