Cykl Czerwonego - Zielonego - Refaktora dla TDD jest dobrze ustalony i zaakceptowany. Piszemy jeden nieudany test jednostkowy i sprawiamy, że przechodzi on tak prosto, jak to możliwe. Jakie są korzyści z tego podejścia w porównaniu z pisaniem wielu nieudanych testów jednostkowych dla klasy i sprawianiem, że wszystkie przejdą za jednym razem.
Pakiet testowy nadal chroni Cię przed pisaniem niepoprawnego kodu lub popełnianiem błędów na etapie refaktoryzacji, więc jaka szkoda? Czasami łatwiej jest najpierw napisać wszystkie testy dla klasy (lub modułu) jako formę „zrzutu mózgu”, aby szybko zapisać wszystkie oczekiwane zachowanie za jednym razem.
Odpowiedzi:
Projekt oparty na testach dotyczy poprawnego działania interfejsu API , a nie kodu.
Zaletą napisania najprostszych testów zakończonych niepowodzeniem jest to, że otrzymujesz API (które zasadniczo projektujesz w locie) tak prosto, jak to możliwe. Z przodu.
Wszelkie przyszłe zastosowania (które są następnymi testami, które napiszesz) przejdą od początkowego prostego projektu, zamiast nieoptymalnego projektu, radzącego sobie z bardziej złożonymi przypadkami.
źródło
Kiedy piszesz jeden test, koncentrujesz się na jednej rzeczy.
Dzięki wielu testom koncentrujesz się na wielu zadaniach, więc nie jest to dobry pomysł.
źródło
Jedną z trudności podczas pisania testów jednostkowych jest to, że piszesz kod, a to samo w sobie może potencjalnie być podatne na błędy. Istnieje również możliwość, że będziesz musiał później zmienić swoje testy w wyniku refaktoryzacji podczas pisania kodu implementacyjnego. Dzięki TDD oznacza to, że potencjalnie możesz trochę za bardzo dać się ponieść testom i odkryć, że musisz przepisać wiele zasadniczo „niesprawdzonego” kodu testowego, gdy twoja implementacja dojrzewa w trakcie projektu. Jednym ze sposobów uniknięcia tego rodzaju problemu jest po prostu skupienie się na robieniu jednej rzeczy naraz. Dzięki temu zminimalizujesz wpływ wszelkich zmian na twoje testy.
Oczywiście w dużej mierze sprowadza się to do sposobu pisania kodu testowego. Czy piszesz test jednostkowy dla każdej metody, czy piszesz testy, które koncentrują się na cechach / wymaganiach / zachowaniach? Innym podejściem może być zastosowanie podejścia opartego na zachowaniu z odpowiednią strukturą i skoncentrowanie się na pisaniu testów, jakby były specyfikacjami. Oznaczałoby to albo przyjęcie metody BDD, albo dostosowanie testów BDD, jeśli chcesz trzymać się TDD w bardziej formalny sposób. Alternatywnie możesz całkowicie trzymać się paradygmatu TDD, ale zmienić sposób pisania testów, aby zamiast skupiać się wyłącznie na metodach testowania indywidualnie, testujesz zachowania bardziej ogólnie jako sposób na spełnienie specyfiki wymagań, które wdrażasz.
Niezależnie od tego, jakie podejście podejmiesz, we wszystkich przypadkach, które opisałem powyżej, używasz podejścia polegającego na pierwszym przetestowaniu, więc chociaż może być kuszące, aby po prostu pobrać swój mózg do pięknego zestawu testów, chcesz również walczyć pokusa, by zrobić więcej niż to absolutnie konieczne. Ilekroć mam rozpocząć nowy pakiet testowy, zaczynam powtarzać sobie YAGNI, a czasem nawet wrzucam go do komentarza w moim kodzie, aby przypomnieć mi, żebym skupił się na tym, co jest natychmiastowo ważne i robił tylko minimum wymagane do spełnienia wymagania funkcji, którą zamierzam wdrożyć. Trzymanie się Refaktora Czerwono-Zielonego pomaga zapewnić, że to zrobisz.
źródło
Myślę, że robiąc to, przegapisz proces TDD. Po prostu pisząc wszystkie testy na początku, tak naprawdę nie przechodzisz przez proces opracowywania za pomocą TDD. Po prostu zgadujesz, które testy będą potrzebne. Będzie to zupełnie inny zestaw testów niż te, które kończysz pisaniem, jeśli wykonujesz je pojedynczo podczas opracowywania kodu. (Chyba że twój program będzie trywialny z natury).
źródło
„Piszę” wszystkie testy, które mogę sobie wyobrazić podczas „burzy mózgów”, ale piszę każdy test jako pojedynczy komentarz opisujący test.
Następnie przekonwertowałem jeden test na kod i wykonałem pracę, aby się skompilował i zdał . Często decyduję się, że nie potrzebuję wszystkich testów, które tak myślałem, lub potrzebuję różnych testów, ta informacja pochodzi tylko z pisania kodu, aby testy przebiegły pomyślnie.
Problem polega na tym, że nie możesz napisać testu w kodzie, dopóki nie utworzysz metody i klas, które testuje, ponieważ w przeciwnym razie dostaniesz wiele błędów kompilatora, które przeszkadzają w pracy nad jednym testem naraz.
Teraz, jeśli używasz systemu przypominającego specyfikację, gdy testy są napisane w języku angielskim, możesz poprosić klientów o zgodę na zestaw testów, kiedy masz na to czas, zamiast tworzyć tylko jeden test.
źródło
Ideą TDD są szybkie iteracje.
Jeśli masz dużą liczbę testów, które należy napisać przed napisaniem kodu, trudno jest iteracyjnie refaktoryzować kod.
Bez łatwego refaktoryzacji kodu tracisz wiele zalet TDD.
źródło
W moim (ograniczonym) doświadczeniu z TDD mogę powiedzieć, że za każdym razem, gdy łamałem dyscyplinę pisania jednego testu na raz, sprawy szły źle. Łatwo wpaść w pułapkę. „Och, ta metoda jest trywialna” - myślisz - więc po prostu powalę te dwa inne powiązane testy i ruszam dalej ”. Zastanów się? Nic nie jest tak trywialne, jak się wydaje. Za każdym razem, gdy wpadałem w tę pułapkę, debugowałem coś, co wydawało mi się łatwe, ale okazało się, że mam dziwne narożne skrzynki. A ponieważ napisałem kilka testów jednocześnie, ustalenie, gdzie był błąd, było bardzo ciężkie.
Jeśli potrzebujesz zrzutu informacji, masz wiele opcji:
Zauważ, że nigdzie na tej liście nie ma kompilatora. :-)
źródło
Zakładasz, że wiesz, jak będzie wyglądał Twój kod, zanim go napiszesz. TDD / BDD jest zarówno procesem projektowania / odkrywania, jak i procesem zapewniania jakości. Dla danej funkcji piszesz najprostszy test, który sprawdzi, czy dana funkcja jest spełniona (czasami może to wymagać kilku z powodu złożoności funkcji). Pierwszy test, który piszesz, jest obciążony założeniami, jak będzie wyglądał działający kod. Jeśli napiszesz cały pakiet testowy przed napisaniem pierwszego wiersza kodu, który go obsługuje, robisz litanię niezweryfikowanych założeń. Zamiast tego napisz jedno założenie i zweryfikuj je. Następnie napisz następny. Podczas weryfikacji następnego założenia możesz po prostu złamać wcześniejsze założenie, więc musisz wrócić i zmienić to pierwsze założenie, aby dopasować je do rzeczywistości lub zmienić rzeczywistość, aby pierwsze założenie nadal obowiązywało.
Pomyśl o każdym teście jednostkowym, który piszesz, jako teorii w zeszycie naukowym. Wypełniając notatnik, dowodzisz swoich teorii i tworzysz nowe. Czasami udowodnienie, że nowa teoria obala poprzednią teorię, więc musisz ją naprawić. Łatwiej jest udowodnić jedną teorię naraz niż próbować udowodnić powiedzmy 20 naraz.
źródło
TDD to wysoce iteracyjne podejście, które (z mojego doświadczenia) lepiej pasuje do rzeczywistych sposobów rozwoju. Zazwyczaj moja implementacja kształtuje się stopniowo podczas tego procesu, a każdy krok może przynieść dalsze pytania, spostrzeżenia i pomysły na testowanie. Jest to idealne rozwiązanie, aby skoncentrować się na rzeczywistym zadaniu i jest bardzo wydajne, ponieważ muszę przechowywać ograniczoną liczbę rzeczy w pamięci krótkotrwałej w dowolnym momencie. To z kolei zmniejsza prawdopodobieństwo błędów.
Twój pomysł to w zasadzie podejście Big Test Up Front, z którym IMHO jest trudniejsze w obsłudze i może stać się bardziej marnotrawstwem. Co się stanie, jeśli w połowie pracy zdasz sobie sprawę, że twoje podejście nie jest dobre, Twój interfejs API jest wadliwy i musisz zacząć wszystko od nowa lub zamiast tego użyć biblioteki innej firmy? Potem wiele pracy włożonej w pisanie testów z góry staje się zmarnowanym wysiłkiem.
To powiedziawszy, jeśli to zadziała, w porządku. Mogę sobie wyobrazić, że jeśli pracujesz na podstawie stałej, szczegółowej specyfikacji technicznej, w domenie, z którą masz bliskie doświadczenie i / lub przy dość małym zadaniu, możesz mieć większość lub wszystkie niezbędne przypadki testowe gotowe, a wdrażanie jasne od samego początku początek. Wtedy warto zacząć od napisania wszystkich testów na raz. Jeśli masz doświadczenie, że dzięki temu będziesz bardziej produktywny na dłuższą metę, nie musisz się zbytnio przejmować zasadami :-)
źródło
Oprócz myślenia tylko o jednej rzeczy, jednym z paradygmatów TDD jest napisanie możliwie najmniejszego kodu, aby przejść test. Kiedy piszesz jeden test na raz, o wiele łatwiej jest zobaczyć ścieżkę do napisania wystarczającej ilości kodu, aby ten test mógł zostać zaliczony. Z całym zestawem testów do przejścia, nie przychodzisz do kodu małymi krokami, ale musisz zrobić duży skok, aby wszystkie przebiegły za jednym razem.
Teraz, jeśli nie ograniczysz się do pisania kodu, aby wszyscy przeszli „za jednym razem”, ale raczej piszesz tyle kodu, aby przejść jeden test na raz, może nadal działać. Musisz jednak zachować większą dyscyplinę, aby nie tylko pisać i pisać więcej kodu, niż potrzebujesz. Kiedy zaczniesz tę ścieżkę, pozostawiasz się otwarty na pisanie większej ilości kodu niż opisują testy, co można przetestować , przynajmniej w tym sensie, że nie jest on przeprowadzany przez test i być może w tym sensie, że nie jest potrzebny (lub wykonane) przez dowolny test.
Zrozumienie, co powinna zrobić metoda, takie jak komentarze, historie, specyfikacja funkcjonalna itp., Jest całkowicie dopuszczalne. Chciałbym jednak przełożyć je na testy pojedynczo.
Inną rzeczą, której możesz pominąć, pisząc testy naraz, jest proces myślenia, dzięki któremu zdanie testu może skłonić Cię do myślenia o innych przypadkach testowych. Bez zestawu istniejących testów należy pomyśleć o kolejnym przypadku testowym w kontekście ostatniego testu pozytywnego. Jak już powiedziałem, dobre wyobrażenie o tym, co ma zrobić metoda, jest bardzo dobre, ale wiele razy znalazłem nowe możliwości, których nie rozważałem a priori, ale które pojawiły się tylko w trakcie pisania testy. Istnieje niebezpieczeństwo, że możesz je przegapić, chyba że przyzwyczaisz się myśleć, jakie nowe testy mogę napisać, których jeszcze nie mam.
źródło
Pracowałem nad projektem, w którym programiści, którzy napisali (nieudane) testy, różnili się od programistów wdrażających niezbędny kod, aby je przejść, i stwierdziłem, że jest on naprawdę skuteczny.
W takim przypadku tylko testy związane z bieżącą iteracją zostały napisane jeden raz. To, co sugerujesz, jest całkowicie możliwe w tego rodzaju scenariuszu.
źródło
źródło
Cykl Red-Green-Refactor to lista kontrolna przeznaczona dla deweloperów, którzy nie znają TDD. Powiedziałbym, że dobrze jest postępować zgodnie z tą listą kontrolną, dopóki nie wiesz, kiedy i kiedy możesz ją złamać (to znaczy, dopóki nie wiesz, że nie musisz zadawać tego pytania podczas stackoverflow :)
Po ukończeniu TDD przez prawie dekadę mogę powiedzieć, że bardzo rzadko, jeśli w ogóle, piszę wiele nieudanych testów przed napisaniem kodu produkcyjnego.
źródło
Opisujesz BDD, gdzie jakiś zewnętrzny interesariusz ma wykonywalną specyfikację. Może to być korzystne, jeśli istnieje z góry określona specyfikacja (na przykład specyfikacja formatu, standard przemysłowy lub gdy programista nie jest ekspertem w dziedzinie).
Normalnym podejściem jest wówczas stopniowe obejmowanie coraz większej liczby testów akceptacyjnych, co jest postępem widocznym dla kierownika projektu i klienta.
Zazwyczaj testy te są określone i wykonywane w ramach BDD, takich jak Cucumber, Fitnesse lub niektóre podobne.
Nie jest to jednak coś, co mieszasz z testami jednostkowymi, które są znacznie bliższe szczegółowym szczegółom implementacji z wieloma przypadkowymi krawędziami związanymi z API, problemami z inicjalizacją itp. Silnie skoncentrowanymi na testowanym elemencie , który jest artefaktem implementacji .
Dyscyplina czerwono-zielonego refaktora ma wiele zalet, a jedyną zaletą, na którą możesz liczyć, wpisując je z góry, jest osiągnięcie progu rentowności.
źródło
Jeden test na raz: główną zaletą jest skupienie się na jednej rzeczy. Pomyśl o projektowaniu w pierwszej kolejności: możesz wejść głęboko i pozostać skupionym dzięki pętli szybkiego sprzężenia zwrotnego. Możesz jednak pominąć zakres całego problemu! Właśnie w tym momencie wchodzi w grę (duża) refaktoryzacja. Bez niego TDD nie działa.
Wszystkie testy: analiza i projektowanie mogą ujawnić więcej zakresu problemu. Pomyśl o pierwszym projekcie. Analizujesz problem pod wieloma kątami i dodajesz doświadczenia. Jest to z natury trudniejsze, ale może przynieść ciekawe korzyści - mniej refaktoryzacji - jeśli zrobisz to „wystarczająco dużo”. Strzeż się, że łatwo jest przesadzić z analizą, a mimo to całkowicie nie trafić.
Trudno mi ogólnie zalecić wybranie jednego lub drugiego, ponieważ czynników jest wiele: doświadczenie (szczególnie z tym samym problemem), wiedza i umiejętności w dziedzinie, łatwość kodowania do refaktoryzacji, złożoność problemu ...
Sądzę, że jeśli skupimy się bardziej na typowych aplikacjach biznesowych, wówczas TDD z podejściem polegającym na szybkim prawie próbach i błędach zwykle wygrywa pod względem skuteczności.
źródło
Zakładając, że twoja platforma testowa to obsługuje, sugerowałbym, że zamiast implementować testy, które chcesz braindump, zamiast tego napisz opisowe testy oczekujące, które później zaimplementujesz. Na przykład, jeśli twój interfejs API powinien wykonywać foo i bar, ale nie biz, po prostu dodaj następujący kod (ten przykład jest w rspec) do swojego zestawu testów, a następnie atakuj je jeden po drugim. Szybko myślisz i możesz rozwiązać wszystkie swoje problemy jeden po drugim. Po przejściu wszystkich testów dowiesz się, kiedy rozwiązałeś wszystkie problemy, które miałeś podczas braindumpa.
źródło