Mam ponad 2-letnie doświadczenie w tworzeniu aplikacji. W ciągu tych dwóch lat moje podejście do rozwoju było następujące
- Analizuj wymagania
- Tożsamość Główny komponent / Obiekty, Wymagane funkcje, Zachowanie, Proces i ich ograniczenia
- Twórz klasy, relacje między nimi, ograniczenia dotyczące zachowania i stanów obiektów
- Twórz funkcje, przetwarzaj z ograniczeniami behawioralnymi zgodnie z wymaganiami
- Ręcznie przetestuj aplikację
- Jeśli zmiany wymagań zmodyfikują komponent / funkcje, należy ręcznie przetestować aplikację
Niedawno zapoznałem się z TDD i uważam, że jest to bardzo dobry sposób na programowanie, ponieważ opracowany kod ma poważne powody, aby istnieć, a wiele problemów po wdrożeniu zostało zmniejszonych.
Ale mój problem polega na tym, że nie jestem w stanie najpierw utworzyć testów, raczej identyfikuję komponenty i po prostu piszę dla nich test, zanim zacznę pisać komponenty. moje pytanie brzmi
- Czy robię to, prawda? Jeśli nie to co dokładnie muszę zmienić
- Czy jest jakiś sposób na stwierdzenie, czy napisany test jest wystarczający?
- Czy dobrą praktyką jest pisanie testu pod kątem bardzo prostej funkcjonalności, która może być równoważna 1 + 1 = 2, czy może to tylko overplay?
- Czy dobrze jest zmienić funkcjonalność i odpowiednio sprawdzić, czy zmieniają się wymagania?
Odpowiedzi:
Trudno powiedzieć na podstawie tego krótkiego opisu, ale podejrzewam, że nie robisz tego dobrze. Uwaga: nie mówię, że to, co robisz, nie działa lub jest w jakiś sposób złe, ale nie robisz TDD. Środkowe „D” oznacza „Driven”, testy napędzają wszystko, proces rozwoju, kod, projekt, architekturę, wszystko .
Testy mówią ci, co napisać, kiedy to napisać, co napisać dalej, kiedy przestać pisać. Mówią o projekcie i architekturze. (Projekt i architektura wyłaniają się z kodu poprzez refaktoryzację.) TDD nie polega na testowaniu. Tu nawet nie chodzi o pisanie testów: TDD polega na tym, aby testy cię poprowadziły, napisanie ich jako pierwszego jest po prostu niezbędnym warunkiem do tego.
Nie ma znaczenia, czy faktycznie zapisujesz kod, czy masz go w pełni rozwinięty: piszesz (szkielety) kodu w głowie, a następnie piszesz testy dla tego kodu. To nie TDD.
Porzucenie tego nawyku jest trudne . Naprawdę bardzo ciężko. Wydaje się to szczególnie trudne dla doświadczonych programistów.
Keith Braithwaite stworzył ćwiczenie, które nazywa TDD tak, jakbyś to rozumiał . Składa się z zestawu zasad (opartych na trzech regułach TDD wuja Boba Martina , ale o wiele surowszych), których należy ściśle przestrzegać i które mają na celu bardziej rygorystyczne stosowanie TDD. Działa najlepiej z programowaniem par (aby twoja para mogła upewnić się, że nie łamiesz zasad) i instruktorem.
Reguły są następujące:
Zazwyczaj doprowadzi to do bardzo różnych projektów niż często praktykowana „pseudo-TDD” polegająca na wyobrażaniu sobie w głowie, jaki powinien być projekt, a następnie pisanie testów w celu wymuszenia tego projektu, wdrożenie projektu, który już przewidziałeś przed napisaniem testy ”.
Kiedy grupa ludzi wdraża coś w rodzaju gry w kółko i krzyżyk za pomocą pseudo-TDD, zwykle kończy się to bardzo podobnymi projektami, obejmującymi jakąś
Board
klasę z tablicą 3 × 3Integer
s. I przynajmniej część programistów faktycznie napisała tę klasę bez testów, ponieważ „wiedzą, że będą jej potrzebować” lub „będą potrzebować czegoś, na co mogliby napisać swoje testy”. Jednak, gdy zmusisz tę samą grupę do zastosowania TDD tak, jak chcesz, często kończą się szeroką różnorodnością bardzo różnych projektów, często nie wykorzystując niczego nawet zdalnie podobnego doBoard
.Gdy pokrywają wszystkie wymagania biznesowe. Testy są kodowaniem wymagań systemowych.
Znowu masz to odwrotnie: nie piszesz testów funkcjonalności. Piszesz funkcjonalność do testów. Jeśli funkcjonalność umożliwiająca zdanie testu jest trywialna, to świetnie! Właśnie spełniłeś wymagania systemowe i nie musiałeś nawet ciężko nad tym pracować!
Nie. Odwrotnie. Jeśli wymaganie się zmienia, zmieniasz test, który odpowiada temu wymaganiu, obserwujesz, jak się nie udaje, a następnie zmieniasz kod, aby przejść pomyślnie. Testy są zawsze najważniejsze.
Trudno to zrobić. Potrzebujesz dziesiątek, może setek godzin celowej praktyki , aby zbudować coś w rodzaju „pamięci mięśniowej”, aby dojść do punktu, w którym, gdy zbliża się termin i jesteś pod presją, nawet nie musisz o tym myśleć , a robienie tego staje się najszybszym i najbardziej naturalnym sposobem pracy.
źródło
Board
klasy z Tablica 3x3int
s (lub coś takiego). Natomiast jeśli zmusisz ich do wykonania TDDAIYMI, często kończą się tworzeniem mini-DSL do przechwytywania wiedzy o domenie. To oczywiście tylko anegdota. Przydatne byłyby statystycznie i naukowo uzasadnione badanie, ale jak to często bywa w przypadku takich badań, są one albo o wiele za małe, albo o wiele za drogie.Opisujesz swoje podejście do programowania jako proces „z góry na dół” - zaczynasz od wyższego poziomu abstrakcji i coraz bardziej zagłębiasz się w szczegóły. TDD, przynajmniej w formie popularnej, jest techniką „oddolną”. A dla kogoś, kto pracuje głównie „z góry na dół”, może być bardzo nietypowe, aby pracować „z dołu do góry”.
Jak więc wnieść więcej „TDD” do procesu rozwoju? Po pierwsze, zakładam, że twój rzeczywisty proces rozwoju nie zawsze jest tak „odgórny”, jak to opisano powyżej. Po kroku 2 prawdopodobnie zidentyfikujesz niektóre komponenty, które są niezależne od innych komponentów. Czasami decydujesz się najpierw na wdrożenie tych komponentów. Szczegóły publicznego interfejsu API tych komponentów prawdopodobnie nie odpowiadają Twoim wymaganiom, szczegóły również podążają za decyzjami projektowymi. W tym miejscu możesz zacząć od TDD: wyobraź sobie, jak zamierzasz korzystać z komponentu i jak faktycznie będziesz korzystać z API. A kiedy zaczynasz kodować takie użycie interfejsu API w formie testu, właśnie zacząłeś od TDD.
Po drugie, możesz wykonywać TDD nawet wtedy, gdy zamierzasz kodować więcej „z góry na dół”, zaczynając od komponentów, które najpierw zależą od innych nieistniejących komponentów. Musisz nauczyć się, jak najpierw „wyśmiewać” te inne zależności. Umożliwi to tworzenie i testowanie komponentów wysokiego poziomu przed przejściem do komponentów niższego poziomu. Bardzo szczegółowy przykład robienia TDD w sposób odgórny można znaleźć w tym blogu Ralfa Westphala .
źródło
Radzisz sobie dobrze.
Tak, użyj narzędzia pokrycia testowego / kodu . Martin Fowler oferuje kilka dobrych porad na temat pokrycia testowego.
Ogólnie rzecz biorąc, każda funkcja, metoda, komponent itp., Które mogą przynieść pewien wynik, biorąc pod uwagę niektóre dane wejściowe, jest dobrym kandydatem do testu jednostkowego. Jednak, podobnie jak w przypadku większości rzeczy w życiu (inżynieryjnym), należy wziąć pod uwagę swoje kompromisy: czy wysiłek jest zrównoważony przez napisanie testu jednostkowego, co skutkuje bardziej stabilną bazą kodu na dłuższą metę? Ogólnie rzecz biorąc, najpierw wybierz kod testowy dla kluczowych / krytycznych funkcji. Później, jeśli okaże się, że istnieją błędy związane z pewną niesprawdzoną częścią kodu, dodaj więcej testów.
Zaletą posiadania automatycznych testów jest to, że natychmiast zobaczysz, czy zmiana złamie poprzednie twierdzenia. Jeśli oczekujesz tego ze względu na zmienione wymagania, tak, możesz zmienić kod testowy (w rzeczywistości w czystym TDD najpierw zmieniłbyś testy zgodnie z wymaganiami, a następnie dostosowałeś kod, aż spełni nowe wymagania).
źródło
Najpierw pisanie testów to zupełnie inne podejście do pisania oprogramowania. Testy są nie tylko narzędziem do prawidłowej weryfikacji funkcjonalności kodu (wszystkie przechodzą), ale siłą, która określa projekt. Chociaż zasięg testowy może być użyteczną miarą, nie może być celem samym w sobie - celem TDD nie jest uzyskanie dobrego% pokrycia kodu, ale pomyślenie o testowalności kodu przed jego napisaniem.
Jeśli najpierw masz problemy z pisaniem testów, zdecydowanie polecam wykonanie sesji programowania w parze z kimś, kto ma doświadczenie w TDD, abyś miał doświadczenie w „sposobie myślenia” o całym podejściu.
Inną dobrą rzeczą jest obejrzenie wideo online, w którym oprogramowanie jest rozwijane przy użyciu TDD od pierwszej linii. Dobry, który kiedyś przedstawiałem TDD, to Let's Play TDD Jamesa Shore'a. Spójrz, zilustruje to, jak działa powstające projektowanie, jakie pytania powinieneś sobie zadać podczas pisania testów oraz w jaki sposób nowe klasy i metody są tworzone, refaktoryzowane i powtarzane.
Uważam, że to niewłaściwe pytanie. Kiedy robisz TDD, wybrałeś TDD i nowy projekt jako sposób pisania oprogramowania. Jeśli jakakolwiek nowa funkcja, którą musisz dodać, zawsze zaczyna się od testu, zawsze będzie dostępna.
Oczywiście to zależy, użyj własnego osądu. Wolę nie pisać testów na parametrach kontroli zerowej, jeśli metoda nie jest częścią publicznego API, ale inaczej, dlaczego nie potwierdziłbyś, że metoda Add (a, b) rzeczywiście zwraca a + b?
Ponownie, gdy zmieniasz lub dodajesz nową funkcjonalność do swojego kodu, zaczynasz od testu, niezależnie od tego, czy dodajesz nowy test, czy zmieniasz istniejący, gdy zmieniają się wymagania.
źródło