W moim obecnym projekcie (gra w C ++) zdecydowałem, że będę używać 100% Test Driven Development podczas programowania.
Pod względem jakości kodu było to świetne. Mój kod nigdy nie był tak dobrze zaprojektowany ani wolny od błędów. Nie wzdrygam się podczas przeglądania kodu, który napisałem rok temu na początku projektu, i zyskałem znacznie lepsze wyczucie, jak ustrukturyzować rzeczy, aby nie tylko łatwiej było je testować, ale także by było prostsze w implementacji i użyciu .
Jednak ... minął rok odkąd zacząłem projekt. To prawda, że mogę nad tym pracować tylko w wolnym czasie, ale TDD wciąż znacznie mnie spowalnia w porównaniu do tego, do czego jestem przyzwyczajony. Czytałem, że wolniejsza prędkość rozwoju z czasem staje się lepsza i zdecydowanie wymyślam testy o wiele łatwiej niż kiedyś, ale pracowałem już od roku i nadal pracuję w tempie ślimaka.
Za każdym razem, gdy myślę o następnym kroku, który wymaga pracy, muszę za każdym razem się zatrzymać i zastanowić się, jak napisać test, aby pozwolić mi napisać właściwy kod. Czasami utknąłem na godziny, wiedząc dokładnie, jaki kod chcę napisać, ale nie wiem, jak go rozbić na tyle dokładnie, aby w pełni pokryć go testami. Innym razem szybko wymyślę tuzin testów i spędzę godzinę na pisaniu testów, aby pokryć niewielki fragment prawdziwego kodu, którego napisanie zajęłoby kilka minut.
Lub po ukończeniu 50. testu obejmującego konkretny byt w grze oraz wszystkie aspekty jego tworzenia i użytkowania, patrzę na moją listę rzeczy do zrobienia i widzę następny byt do zakodowania, i przerażony na myśl o pisaniu kolejne 50 podobnych testów, aby go wdrożyć.
Doszło do tego, że patrząc na postępy z ubiegłego roku, rozważam porzucenie TDD w celu „ukończenia tego cholernego projektu”. Jednak rezygnacja z dostarczonej z nią jakości kodu nie jest czymś, na co czekam. Obawiam się, że jeśli przestanę pisać testy, to wyślizgnę się z nawyku tworzenia kodu tak modułowego i testowalnego.
Czy może robię coś złego, żeby być w tym tak powolnym? Czy istnieją alternatywy, które przyspieszają produktywność bez całkowitej utraty korzyści? BERBEĆ? Mniejszy zasięg testu? Jak inni ludzie przeżywają TDD bez zabijania całej produktywności i motywacji?
źródło
Odpowiedzi:
Pozwól, że zacznę od podziękowania za podzielenie się swoimi doświadczeniami i wyrażenia swoich obaw ... które muszę powiedzieć, nie są rzadkie.
I to prowadzi mnie do ostatniego pytania: Jak mogę się poprawić? Moja (lub An) odpowiedź brzmi: czytaj, odzwierciedlaj i ćwicz.
np. ostatnio pilnuję
źródło
Nie potrzebujesz 100% procent pokrycia testowego. Bądź pragmatyczny.
źródło
a = x + y
i chociaż wszystkie wiersze w kodzie zostały wykonane w testach, testy były testowane tylko w przypadku, gdy y = 0, więc błąd (powinien byća = x - y
) nigdy nie został znaleziony w testach.To właściwie fałsz.
Bez TDD spędzasz kilka tygodni na pisaniu kodu, który w większości działa, a następny rok spędzasz na „testowaniu” i naprawianiu wielu (ale nie wszystkich) błędów.
Dzięki TDD spędzasz rok na pisaniu kodu, który faktycznie działa. Następnie wykonujesz końcowe testy integracyjne przez kilka tygodni.
Upływający czas prawdopodobnie będzie taki sam. Oprogramowanie TDD będzie znacznie lepszej jakości.
źródło
To sprawia, że zastanawiam się, jak bardzo śledzisz krok „Refaktoryzacja” TDD.
Po przejściu wszystkich testów nadszedł czas, aby zmienić kod i usunąć duplikaty. Chociaż ludzie zwykle o tym pamiętają, czasami zapominają, że nadszedł czas również na przefiltrowanie swoich testów , usunięcie duplikacji i uproszczenie.
Jeśli masz dwa podmioty, które łączą się w jeden, aby umożliwić ponowne użycie kodu, rozważ połączenie ich testów. Naprawdę wystarczy przetestować różnice przyrostowe w kodzie. Jeśli nie regularnie przeprowadzasz konserwacji swoich testów, mogą one szybko stać się nieporęczne.
Kilka filozoficznych punktów na temat TDD, które mogą być pomocne:
EDYCJA: Jeśli chodzi o filozofię testów jednostkowych, myślę, że może to być dla ciebie interesujące: The Way of Testivus
I bardziej praktyczny, jeśli niekoniecznie bardzo pomocny, punkt:
źródło
Bardzo interesujące pytanie.
Co ważne, należy zauważyć, że C ++ nie jest bardzo łatwy do przetestowania, a gra jest ogólnie bardzo złym kandydatem na TDD. Nie można sprawdzić, czy OpenGL / DirectX z łatwością rysuje trójkąt czerwony ze sterownikiem X, a żółty ze sterownikiem Y. Jeśli mapa wypukłości normalny wektor nie zostanie odwrócony po przekształceniu modułu cieniującego. Nie można także testować problemów z przycinaniem w wersjach sterowników z różnymi szczegółami i tak dalej. Niezdefiniowane zachowanie podczas rysowania z powodu niepoprawnych wywołań można również przetestować tylko z dokładnym przeglądem kodu i dostępnym zestawem SDK. Dźwięk jest również złym kandydatem. Wielowątkowość, która znów jest dość ważna w grach, jest prawie bezużyteczna w testowaniu jednostkowym. To jest trudne.
Zasadniczo gry to dużo GUI, dźwięku i wątków. GUI, nawet ze standardowymi komponentami, do których można wysłać WM_, jest trudne do przetestowania w jednostce.
Więc co możesz przetestować, to klasy ładujące model, klasy ładujące tekstury, biblioteki macierzy i niektóre inne, które nie zawierają dużo kodu i, często, niezbyt przydatne, jeśli jest to tylko twój pierwszy projekt. Są one również spakowane w zastrzeżonych formatach, więc nie jest prawdopodobne, że dane wejściowe innych firm mogą się znacznie różnić, chyba że zwolnisz narzędzia do modowania itp.
Z drugiej strony nie jestem guru TDD ani ewangelistą, więc weź to wszystko z odrobiną soli.
Prawdopodobnie napisałbym kilka testów dla głównych podstawowych komponentów (na przykład biblioteki macierzy, biblioteki obrazów). Dodaj kilka
abort()
nieoczekiwanych danych wejściowych do każdej funkcji. A co najważniejsze, skoncentruj się na odpornym / odpornym kodzie, który nie pęka łatwo.Jeśli chodzi o jeden błąd, sprytne użycie C ++, RAII i dobry projekt znacznie temu zapobiegają.
Zasadniczo masz wiele do zrobienia, aby omówić podstawy, jeśli chcesz wydać grę. Nie jestem pewien, czy TDD pomoże.
źródło
Zgadzam się z innymi odpowiedziami, ale chcę również dodać bardzo ważną kwestię: koszty refaktoryzacji !!
Dzięki dobrze napisanym testom jednostkowym możesz bezpiecznie robić ponowne zapisywanie kodu. Po pierwsze, dobrze napisane testy jednostkowe zapewniają doskonałą dokumentację zamiarów twojego kodu. Po drugie, wszelkie niefortunne skutki uboczne refaktoryzacji zostaną wykryte w istniejącym pakiecie testowym. W ten sposób masz zagwarantowane, że założenia twojego starego kodu są prawdziwe również dla twojego nowego kodu.
źródło
To całkowicie różni się od moich doświadczeń. Jesteś albo niesamowicie inteligentny i piszesz kod bez błędów (np. Wyłączony przez jeden błąd), albo nie zdajesz sobie sprawy, że twój kod zawiera błędy, które uniemożliwiają działanie twojego programu, a więc nie są właściwie ukończone.
TDD polega na pokorze, aby wiedzieć, że ty (i ja!) Popełniasz błędy.
Dla mnie czas pisania unittestów jest więcej niż zaoszczędzony w skróconym czasie debugowania dla projektów, które są wykonywane przy użyciu TDD od samego początku.
Jeśli nie popełniasz błędów, być może TDD nie jest dla ciebie tak ważne, jak dla mnie!
źródło
Mam tylko kilka uwag:
Wygląda na to, że próbujesz wszystko przetestować . Prawdopodobnie nie powinieneś, po prostu przypadki wysokiego ryzyka i krawędzi danego fragmentu kodu / metody. Jestem prawie pewien, że obowiązuje zasada 80/20: Wydajesz 80% na pisanie testów dla ostatnich 20% twojego kodu lub przypadków, które nie są objęte.
Priorytet. Zyskaj sprawne tworzenie oprogramowania i zrób listę rzeczy, które naprawdę musisz zrobić, aby wypuścić je w ciągu jednego miesiąca. Następnie zwolnij, tak po prostu. To sprawi, że pomyślisz o priorytecie funkcji. Tak, byłoby fajnie, gdyby twoja postać mogła wykonać backflipa, ale czy ma wartość biznesową ?
TDD jest dobre, ale tylko wtedy, gdy nie dążysz do 100% pokrycia testowego, i nie dzieje się tak, jeśli nie pozwala ci to generować rzeczywistej wartości biznesowej (tj. Funkcji, rzeczy, które dodają coś do twojej gry).
źródło
Tak, pisanie testów i kodu może trwać dłużej niż pisanie kodu - ale pisanie kodu i powiązanych testów jednostkowych (przy użyciu TDD) jest znacznie bardziej przewidywalne niż pisanie kodu, a następnie debugowanie go.
Debugowanie jest prawie wyeliminowane, gdy używa się TDD - co sprawia, że cały proces programowania jest znacznie bardziej przewidywalny, a na koniec - prawdopodobnie szybszy.
Ciągłe refaktoryzowanie - nie jest możliwe przeprowadzenie poważnego refaktoryzacji bez kompleksowego zestawu testów jednostkowych. Najbardziej skutecznym sposobem na zbudowanie siatki bezpieczeństwa opartej na testach jednostkowych jest TDD. Dobrze przebudowany kod znacznie poprawia ogólną produktywność projektanta / zespołu, który utrzymuje kod.
źródło
Rozważ zawężenie zakresu gry i znajdź ją tam, gdzie ktoś może w nią zagrać lub ją wydać. Utrzymanie standardów testowania bez konieczności czekania zbyt długo na wydanie gry może być środkiem do utrzymania motywacji. Informacje zwrotne od użytkowników mogą zapewnić korzyści w dłuższej perspektywie, a testowanie pozwala czuć się swobodnie dzięki dodatkom i zmianom.
źródło