Staram się owinąć głowę wokół TDD, a konkretnie części programistycznej. Przeglądałem niektóre książki, ale te, które znalazłem, dotyczą głównie części testowej - Historii NUnit, dlaczego testowanie jest dobre, Red / Green / Refactor i jak stworzyć kalkulator strun.
Dobre rzeczy, ale to „tylko” testy jednostkowe, a nie TDD. W szczególności nie rozumiem, w jaki sposób TDD pomaga mi uzyskać dobry projekt, jeśli potrzebuję go, aby rozpocząć testowanie.
Aby to zilustrować, wyobraź sobie następujące 3 wymagania:
- Katalog musi zawierać listę produktów
- Katalog powinien pamiętać, które produkty oglądał użytkownik
- Użytkownicy powinni mieć możliwość wyszukiwania produktu
W tym momencie wiele książek wyciąga magicznego królika z kapelusza i po prostu zagłębia się w „Testowanie usługi produktu”, ale nie wyjaśniają, w jaki sposób doszli do wniosku, że istnieje usługa produktu. To jest część „Rozwój” w TDD, którą próbuję zrozumieć.
Musi istnieć istniejący projekt, ale nigdzie nie można znaleźć rzeczy poza usługami encji (to znaczy: istnieje Produkt, więc powinna istnieć Usługa Produktu) (np. Drugi wymóg wymaga ode mnie pewnej koncepcji Użytkownik, ale gdzie mam umieścić funkcję przypominania? Czy funkcja wyszukiwania jest funkcją usługi ProductService lub osobnej usługi wyszukiwania? Skąd mam wiedzieć, którą wybrać?)
Według SOLID potrzebowałbym UserService, ale jeśli zaprojektuję system bez TDD, mogę skończyć z całą gamą usług Single-Method Services. Czy TDD nie ma przede wszystkim skłonić mnie do odkrycia mojego projektu?
Jestem programistą .net, ale zasoby Java również by działały. Wydaje mi się, że nie ma prawdziwej przykładowej aplikacji ani książki, która dotyczyłaby prawdziwej aplikacji biznesowej. Czy ktoś może podać jasny przykład ilustrujący proces tworzenia projektu przy użyciu TDD?
Odpowiedzi:
Ideą TDD jest zacząć od testowania i od tego pracować. Dlatego przykład „Katalog musi mieć listę produktów” może być postrzegany jako test „Sprawdź produkty w katalogu”, a zatem jest to pierwszy test. Co zawiera katalog? Co zawiera produkt? To są kolejne elementy, a pomysł polega na zebraniu kilku części, które byłyby czymś w rodzaju usługi ProductService, która narodzi się po przejściu pierwszego testu.
Ideą TDD jest rozpoczęcie od testu, a następnie napisanie kodu, który sprawia, że test ten przechodzi jako pierwszy punkt. Testy jednostkowe są częścią tego, tak, ale nie patrzysz na ogólny obraz, który powstaje, zaczynając od testów, a następnie pisząc kod, aby w tym momencie nie było martwych punktów, ponieważ nie ma jeszcze żadnego kodu.
Test Driven Development Tutorial, w którym slajdy 20-22 są kluczowe. Chodzi o to, aby wiedzieć, co powinna zrobić funkcja, napisać test, a następnie zbudować rozwiązanie. Część projektu będzie się różnić, ponieważ w zależności od tego, co jest wymagane, może być lub nie być tak prosta do zrobienia. Kluczową kwestią jest zastosowanie TDD od samego początku, a nie próba wprowadzenia go późno w projekt. Jeśli najpierw zaczniesz od testów, może to pomóc i prawdopodobnie warto w pewnym sensie zauważyć. Jeśli spróbujesz dodać testy później, staje się to czymś, co można odłożyć lub opóźnić. Przydatne mogą być także późniejsze slajdy.
Główną zaletą TDD jest to, że rozpoczynając od testów, nie jesteś początkowo związany z projektem. Dlatego chodzi o zbudowanie testów i stworzenie kodu, który przejdzie te testy jako metodologię programowania. Big Projekt Up przednia może powodować problemy, jak to daje się pomysł blokowania rzeczy na miejsce, które sprawia, że system jest zbudowany, aby być mniej zwinny w końcu.
Robert Harvey dodał to w komentarzach, które warto zaznaczyć w odpowiedzi:
źródło
Za to, co jest warte, TDD pomaga mi szybciej znaleźć najlepszą konstrukcję niż nie robić TDD. Prawdopodobnie wybrałbym najlepszy projekt z nim lub bez niego. Ale ten czas, który spędziłbym na przemyśleniu i zrobieniu kilku ciosów w kodzie, spędziłem zamiast tego na pisaniu testów. I to mniej czasu. Dla mnie. Nie dla każdego. I nawet jeśli zajęłoby to tyle samo czasu, dałoby mi to zestaw testów, dzięki czemu refaktoryzacja byłaby bezpieczniejsza, co prowadziłoby do jeszcze lepszego kodu na końcu.
Jak to robi?
Po pierwsze, zachęca mnie do myślenia o każdej klasie jako o usłudze dla jakiegoś kodu klienta. Lepszy kod wynika z myślenia o tym, jak kod wywołujący chce korzystać z interfejsu API, zamiast martwienia się o to, jak powinien on wyglądać.
Po drugie, powstrzymuje mnie to od pisania zbyt dużej złożoności cyklometrycznej w jednej metodzie, podczas gdy ja o tym myślę. Każda dodatkowa ścieżka prowadząca do metody może podwoić liczbę testów, które muszę wykonać. Zwykłe lenistwo dyktuje, że po dodaniu zbyt dużej logiki i muszę napisać 16 testów, aby dodać jeden warunek, nadszedł czas, aby wyciągnąć część z nich do innej metody / klasy i przetestować osobno.
To naprawdę takie proste. To nie jest magiczne narzędzie do projektowania.
źródło
Wymagania te należy przekształcić w kategoriach ludzkich. Kto chce wiedzieć, które produkty użytkownik oglądał wcześniej? Użytkownik? Sprzedawca?
W jaki sposób? Wg nazwy? Według marki? Pierwszym krokiem w rozwoju opartym na testach jest zdefiniowanie testu, na przykład:
>
Jeśli są to jedyne wymagania, z pewnością nie zrobiłbym skoku, aby utworzyć usługę ProductService. Mogę stworzyć bardzo prostą stronę internetową ze statyczną listą produktów. To działałoby idealnie, dopóki nie przejdziesz do wymagań dodawania i usuwania produktów. W tym momencie mogę zdecydować, że najłatwiej jest użyć relacyjnej bazy danych i ORM i utworzyć klasę produktu odwzorowaną na pojedynczą tabelę. Nadal nie ma usługi produktu. Klasy takie jak ProductService zostaną utworzone, kiedy i jeśli będą potrzebne. Może być wiele żądań internetowych, które wymagają wykonania tych samych zapytań lub aktualizacji. Następnie zostanie utworzona klasa ProductService, aby zapobiec duplikowaniu kodu.
Podsumowując, TDD steruje kodem, który ma zostać napisany. Projektowanie odbywa się podczas dokonywania wyborów implementacyjnych, a następnie przekodowywania kodu na klasy w celu wyeliminowania powielania i kontrolowania zależności. Podczas dodawania kodu musisz utworzyć nowe klasy, aby zachować kod SOLID. Ale nie musisz z góry decydować, że będziesz potrzebować klasy Product i ProductService. Może się okazać, że życie jest w porządku z klasą produktu.
źródło
ProductService
. Ale w jaki sposób TDD powiedziało ci, że potrzebujesz bazy danych i ORM?Inni mogą się nie zgadzać, ale dla mnie wiele nowszych metodologii opiera się na założeniu, że programista zrobi większość tego, co starsze metodologie wyraziły z przyzwyczajenia lub osobistej dumy, że programista zwykle robi coś, co jest dość oczywiste dla nich, a praca jest zamknięta w czystym języku lub czystszych częściach nieco niechlujnego języka, abyś mógł wykonać całą działalność testową.
Kilka przykładów, w których natknąłem się na to w przeszłości:
Weź grupę wykonawców specjalizacji i powiedz im, że ich zespół jest zwinny i najpierw testuje. Często nie mają innego zwyczaju, niż pracować zgodnie ze specyfikacją i nie martwią się o jakość pracy, o ile trwa ona wystarczająco długo, aby zakończyć projekt.
Najpierw spróbuj zrobić coś nowego. Spędź dużo czasu na zrywaniu testów, gdy odkryjesz, że różne podejścia i interfejsy to bzdury.
Koduj coś na niskim poziomie i albo daj się ponieść klęskom z powodu braku zasięgu, albo napisz wiele testów, które nie mają tak dużej wartości, ponieważ nie możesz kpić z podstawowych zachowań, z którymi jesteś związany.
Jeśli robisz TDD i to działa na twoje, dobre dla ciebie, ale jest wiele rzeczy (całe prace lub etapy projektu) tam, gdzie to po prostu nie dodaje wartości.
Twój przykład brzmi, jakbyś nie był jeszcze w fazie projektowania, więc albo musisz porozmawiać o architekturze, albo jesteś prototypem. Moim zdaniem musisz najpierw przejść przez niektóre z nich.
źródło
Jestem przekonany, że TDD jest bardzo cennym podejściem do szczegółowego projektu systemu - tj. Interfejsów API i modelu obiektowego. Aby jednak dojść do sedna projektu, w którym zacząłbyś używać TDD, musisz mieć duży obraz projektu, który został już w jakiś sposób modelowany i musisz mieć duży obraz architektury, który został już w jakiś sposób modelowany. @ user414076 parafrazuje Roberta Martina jako pomysł na projekt, ale nie będący z nim małżeństwem. Dokładnie. Wniosek - TDD nie jest jedynym działaniem projektowym, jest to sposób, w jaki dopracowywane są szczegóły projektu. TDD musi być poprzedzone innymi działaniami projektowymi i pasować do ogólnego podejścia (takiego jak Agile), które dotyczy sposobu tworzenia i ewolucji całego projektu.
FYI - dwie książki, które polecam na ten temat, które dają namacalne i realistyczne przykłady:
Rosnące oprogramowanie obiektowe oparte na testach - wyjaśnia i podaje pełny przykład projektu. To książka o projektowaniu, a nie testowaniu . Testowanie służy do określania oczekiwanego zachowania podczas działań projektowych.
testowanie rozwoju Praktyczny przewodnik - powolny krok po kroku tworzenie kompletnej, choć niewielkiej aplikacji.
źródło
Wykrywanie projektu napędów TTD przez niepowodzenie testu, a nie sukces, dlatego możesz testować nieznane i iteracyjnie ponownie testować, ponieważ nieznane są ostatecznie ujawnione, co ostatecznie prowadzi do kompletnego zestawu testów jednostkowych - bardzo miło jest mieć ciągłą konserwację i bardzo trudno jest spróbować modernizacja po napisaniu / wydaniu kodu.
Na przykład może być wymagane, aby dane wejściowe mogły być w kilku różnych formatach, ale nie wszystkie są jeszcze znane. Za pomocą TDD najpierw napiszesz test, który weryfikuje, czy odpowiednie dane wyjściowe są dostarczane w dowolnym formacie wejściowym. Oczywiście ten test się nie powiedzie, więc piszesz kod do obsługi znanych formatów i ponownie testujesz. Ponieważ nieznane formaty są ujawniane poprzez zbieranie wymagań, nowe testy są pisane przed napisaniem kodu, one również powinny zakończyć się niepowodzeniem. Następnie zapisywany jest nowy kod do obsługi nowych formatów, a wszystkie testy są uruchamiane ponownie, co zmniejsza szansę na regresję.
Pomocne jest również, aby pomyśleć o awarii jednostki jako „niedokończonym” kodzie zamiast „zepsutym” kodzie. TDD pozwala na niedokończone jednostki (oczekiwane awarie), ale zmniejsza występowanie uszkodzonych jednostek (nieoczekiwane awarie).
źródło
W pytaniu jest powiedziane:
Doszli do tego wniosku, myśląc o tym, jak zamierzają przetestować ten produkt. „Jaki to produkt?” „Cóż, moglibyśmy stworzyć usługę”. „Ok, napiszmy test dla takiej usługi”
źródło
Funkcjonalność może mieć wiele projektów, a TDD nie powie ci całkowicie, która z nich jest najlepsza. Nawet jeśli testy pomogą Ci zbudować bardziej modułowy kod, może również doprowadzić do zbudowania modułów, które będą odpowiadały wymaganiom testów, a nie rzeczywistości produkcyjnej. Musisz więc zrozumieć, dokąd zmierzasz i jak wszystko powinno pasować do całego obrazu. Innymi słowy, istnieją wymagania funkcjonalne i niefunkcjonalne, nie zapomnij o ostatnim.
Odnośnie projektowania nawiązuję do książek Roberta C. Martina (Agile Development), ale także Wzorów architektury aplikacji korporacyjnych Martina Fowlera i projektowania sterowników domen. Szczególnie późniejsze jest bardzo systematyczne w wydobywaniu Istot i Relacji z wymagań.
Następnie, gdy dobrze zrozumiesz dostępne opcje, jak zarządzać tymi podmiotami, możesz nakarmić cię podejściem TDD.
źródło
Nie.
Jak możesz przetestować coś, czego nie zaprojektowałeś wcześniej?
To nie są wymagania, to są definicje danych. Nie wiem, jaki jest cel twojego oprogramowania, ale jest mało prawdopodobne, że analitycy mówią w ten sposób.
Musisz wiedzieć, jakie są niezmienniki twojego systemu.
Wymaganiem byłoby coś takiego:
Więc jeśli jest to jedyny wymóg, możesz mieć taką klasę:
Następnie za pomocą TDD napiszesz przypadek testowy przed implementacją metody order ().
Drugi test zakończy się niepowodzeniem, a następnie możesz zaimplementować metodę order () w dowolny sposób.
źródło
Masz całkowitą rację TDD spowoduje dobrą implementację danego projektu. To nie pomoże w procesie projektowania.
źródło
TDD bardzo pomaga, jednak ważną rolę odgrywa tworzenie oprogramowania. Deweloper powinien słuchać pisanego kodu . Refaktoryzacja jest trzecią częścią cyklu TDD. Jest to główny krok, na którym deweloper powinien się skupić i pomyśleć przed przejściem do następnego testu czerwonego. Czy jest jakieś powielanie? Czy stosowane są zasady SOLID? Co z wysoką kohezją i niskim sprzężeniem? Co z imionami? Przyjrzyj się kodowi wyłaniającemu się z testów i sprawdź, czy jest coś, co należy zmienić, przeprojektować. Pytanie kodu i kodu powie ci, jak chce być zaprojektowany. Zwykle piszę zestawy wielu testów, sprawdzam tę listę i tworzę pierwszy prosty projekt, nie musi to być „ostateczny”, zwykle nie jest, ponieważ zmienia się przy dodawaniu nowych testów. Tam właśnie pojawia się projekt.
źródło