Nieco ponad rok temu miałem szczęście, że mogłem zrobić 9-miesięczną przerwę w pracy. Zdecydowałem, że w tym czasie doskonalę swoje umiejętności w języku C #. Zacząłem pracować nad wieloma projektami i zmusiłem się do śledzenia TDD.
To był dość pouczający proces.
Na początku było ciężko, ale z czasem nauczyłem się pisać bardziej testowalny kod (który, jak się okazuje, jest bardziej kodem SOLID), a w trakcie tego procesu doskonaliłem umiejętności projektowania OO.
Teraz wróciłem do siły roboczej i zauważam coś dziwnego.
Wolę nie stosować się do TDD.
Uważam, że TDD spowalnia mnie i sprawia, że trudniej jest zaprojektować czystą aplikację.
Zamiast tego zastosowałem nieco (masowo) inne podejście:
- Wybierz pionowy kawałek pracy
- Opracuj działający prototyp
- Refaktoryzuj, aż wszystko będzie ładne i uporządkowane
- Usiądź i doceń pięknie napisany przeze mnie SOLIDNY i testowalny kod.
Być może zauważyłeś, że krok 1 nie „zdefiniował publicznej powierzchni mojego testowego celu”, a krok 2 nie „przetestował bejesusa z tej publicznej powierzchni”. Być może zauważyłeś również, że żaden z kroków nie obejmuje testowania. Piszę testowalny kod, ale go jeszcze nie testuję ... jeszcze.
Teraz chciałbym wyjaśnić, że tak naprawdę nie rezygnuję z żadnych testów. Kod, który piszę, działa . Działa, ponieważ testuję to ręcznie.
Chciałbym również wyjaśnić, że nie rezygnuję też ze wszystkich testów automatycznych. To jest mój proces jest inny. I dlatego zadaję to pytanie.
TDD w teorii. Nie w praktyce.
Mój proces ewoluował nieco i osiągnąłem równowagę między TDD a brakiem testów, które uważam za bardzo produktywne i racjonalnie bezpieczne. Wygląda to następująco:
- Wykonaj działający pionowy kawałek pracy z myślą o testowaniu, ale nie pisz żadnych testów.
- Jeśli później (np. Miesiąc później) ten kawałek wymaga modyfikacji
- Napisz testy jednostkowe, testy integracyjne, testy behawioralne itp., Które gwarantują, że fragment pracy jest poprawny
- Zmodyfikuj kod
- Jeśli ten kawałek nie wymaga modyfikacji,
- Nic nie robić
Po prostu przenosząc ciężar pisania testów przed napisaniem kodu na przed modyfikacją kodu, byłem w stanie stworzyć znacznie więcej działającego kodu. A kiedy zaczynam pisać testy, piszę o wiele mniej, ale pokrywam prawie tyle samo gruntu (wyższy ROI).
Podoba mi się ten proces, ale obawiam się, że może nie być dobrze skalowany. Sukces zależy od tego, czy programiści starają się pisać testy przed zmianą. I to wydaje się dość dużym ryzykiem. Ale TDD ma takie samo ryzyko.
Czy więc zamierzam [BT] DD do diabła, czy jest to powszechna forma pragmatycznego kodowania i testowania?
Chciałbym dalej pracować w ten sposób. Co mogę zrobić, aby ten proces działał na dłuższą metę?
Uwaga:Jestem jedynym programistą w moich projektach i jestem odpowiedzialny za wszystko: zbieranie wymagań, projektowanie, architekturę, testowanie, wdrażanie itp. Podejrzewam, że właśnie dlatego mój proces działa.
źródło
If that slice doesn't need modification
. lizkeogh.com/2012/06/24/beyond-test-driven-developmentOdpowiedzi:
Aby proces działał w dłuższej perspektywie, pisałbym testy podczas pisania kodu.
Co może wydawać się sprzeczne z twoim podejściem. Jednak zadałeś pytanie, więc dam ci moje zdanie:
Nie musisz pisać testów przed kodem. zapomnij o tej czystości. Jednak chcesz napisać testy w tym czasie.
Gdy już uruchomisz kod, poprawiłeś go trochę, usunąłeś kilka błędów (mówimy tutaj o skali godzin), jesteś wtedy na poziomie maksymalnej wiedzy na temat tego, co robi kod. To świetny czas na pisanie testów, które zdobędą Twoją wiedzę.
Pozostawienie tego na później oznacza, że wiedza (naturalnie) z czasem się zmniejszy.
Oznacza to również, że jeśli kiedykolwiek odejdziesz, a ktoś inny przejmie cię, nie będziesz miał natychmiastowego technicznego długu wynikającego z braku udokumentowania (poprzez testy) tego, co robi.
Przede wszystkim „pewnego dnia” może nie nadejść. Możesz zostać potrącony przez autobus lub wsiąść do autobusu na nowe przygody.
Wreszcie, testy ręczne nie są skalowane i często nie obejmują wszystkich urządzeń używanych przez użytkownika końcowego.
źródło
Mimo że TDD jest trudny do wdrożenia w 100%, twoje podejście ma wadę
Wykonaj działający pionowy kawałek pracy
1.1 1 rok mija ....
1.2 Nowy programista rozpoczyna prace nad projektem
Jeśli ten kawałek wymaga modyfikacji
2.3 Analiza składni nazw i parametrów metody „Czyste kodowanie” „GetUnicorn (colourOfUnicorn)”
2.4 Przeczytaj komentarze xml „Dostaje złotego jednorożca (do jazdy) (obvs)”
2.5 Odszukaj oryginalnego twórcę
2.6 Mam nadzieję, że pamiętają, co powinien zrobić kod
2.7 Poproś ich o wyjaśnienie wszystkiego
Napisz testy jednostkowe, testy integracyjne, testy behawioralne itp., Które , mam nadzieję, zagwarantują, że fragment pracy jest poprawny
Myślę, że masz rację, stwierdzając, że testy jednostkowe naprawdę pokazują ich wartość, gdy wymagane są modyfikacje.
źródło
Zgadzam się zarówno z Danielem Hollinrake'em, jak i Ewanem, że pierwszym kluczowym punktem, dlaczego Twoja modyfikacja „tylko jeśli testujesz” działa dobrze, jest:
i że prawdopodobnym drugim kluczowym punktem jest:
Nie sądzę, że TDD zapewnia ogromny wzrost produktywności dla samotnych programistów i może nie poprawić jakości twojego kodu, jeśli już piszesz dobry, czysty kod.
Jednak TDD z pewnością poprawi jakość kodu słabych / niedoświadczonych / przestarzałych programistów, szczególnie gdy przyjdzie czas na modyfikację kodu bez niszczenia czegokolwiek innego. Co więcej, jeśli osoba modyfikująca kod nie jest tą samą osobą, która napisała kod pierwotnie lub upłynęło kilka miesięcy.
Innymi słowy, myślę, że TDD jest zarówno dobrą praktyką do poprawy jakości twojego kodu (jak się przyznajesz), ale także (i co ważniejsze) rodzajem zabezpieczenia, gdy pracujesz z przeciętnymi lub przeciętnymi programistami (powiedzmy, z innego dział lub inna firma), co jest znacznie częstszą sytuacją niż praca solo.
źródło
Dla mnie kluczową rzeczą wydaje się być to:
To działa dla ciebie i tworzysz ładny, czysty kod (zakładam!). Jedyne, co powiedziałbym, że musisz zrobić, to stworzyć uprząż testową, aby inni programiści mogli wejść i mieć pewność wprowadzania zmian. Również uprząż testowa zapewnia spójność działania kodu.
Myślę, że twoje podejście jest podobne do mojego. Zwykle jestem jedynym programistą w moich projektach. Przekonałem się, że docenienie TDD umożliwiło mi pisanie mniejszych funkcji i czystszego kodu, ale dodaję testy, pisząc kod jako test uprzęży. W ten sposób, gdy kod ewoluuje i zmienia się funkcjonalność, mogę być całkiem pewny, że wprowadzam zmiany.
Drugim powodem pisania testów jest to, że uważam, że są one formą dokumentacji. Mogą wyjaśnić moje rozumowanie, dlaczego powstała funkcja. Ale tutaj myślę więcej o rozwoju opartym na zachowaniach.
źródło
Testowanie jednostkowe polega na rozwiązaniu problemu utrzymania kodu. Chociaż są ludzie, którzy twierdzą, że szybciej piszą kod z TDD niż bez niego, nie jestem zaskoczony, że możesz napisać więcej nowego kodu bez pisania testów.
Problemy, które widzę podczas pisania testów tuż przed ich zmianą:
Często muszę szybko wprowadzać zmiany
Możesz ogólnie zaoszczędzić czas, pisząc testy tylko wtedy, gdy ich potrzebujesz, ale nie cały czas jest równy. Spędzanie 2 godzin pisania testów, aby zaoszczędzić 1 godzinę, gdy jestem w trybie kryzysowym - całkowicie tego warte.
Łatwiej jest pisać testy w tym samym czasie, w którym piszę kod
Aby poprawnie napisać testy jednostkowe, musisz zrozumieć kod, który testuję. Często używam testowania jednostkowego jako ćwiczenia w zrozumieniu, ale testowanie jednostkowe istniejącego kodu może być czasochłonne, ponieważ zrozumienie istniejącego kodu jest czasochłonne. Porównaj to z pisaniem testów podczas pisania kodu, a znajdziesz go znacznie szybciej, ponieważ już rozumiesz kod - właśnie go napisałeś!
Definicja starszego kodu autorstwa Michaela Feathersa to kod bez testów. Bez względu na to, czy zgadzasz się z jego definicją, jasne jest, że znaczna część kosztów modyfikacji istniejącego kodu zapewnia upewnienie się, że nadal działa zgodnie z oczekiwaniami, często nawet nie jest jasne, jakie jest oczekiwane zachowanie.
Pisanie testów jednostkowych kompensuje koszty, kodując zrozumienie prawidłowego zachowania, a także zapewniając „przyszłemu nam” łatwy sposób sprawdzenia, czy zachowanie jest prawidłowe.
źródło
To dobre pytanie, a FWIW wrzucę moje dwa centy.
Około rok temu programowałem w Salesforce, platformie, która miała wbudowany mechanizm, który zmusił cię do niekoniecznego pisania testów przed napisaniem kodu , ale zmusił cię do pisania testów w ogóle.
Sposób, w jaki działał, polegał na tym, że system zmusiłby cię do napisania testów i dokonałby obliczenia liczby linii twojego kodu, które zostały przetestowane w procentach. Jeśli cały kod w całej instancji produkcyjnej spadł poniżej 75% przetestowanych. Salesforce nie działa.
W rezultacie za każdym razem, gdy robiłeś coś w Salesforce, musiałeś pisać lub aktualizować testy. Chociaż jestem pewien, że ma to ogromny wpływ na udział w rynku Salesforce, pod względem życia dewelopera był to ogromny ból w dupie .
Często próbujesz przejść przez mały bilet, a potem pojawia się testowanie i podwaja czas programowania, dla funkcji, o której wiesz, że działa.
Potem niezręczna koncepcja TDD przeszła przez nasz dział aż do naszych baz danych. Nasi architekci chcieli przeprowadzić dokładne testy w każdym aspekcie naszego działu IT. Lekki ból w tyłku, spotkać jeszcze większy ból w tyłku.
Wtedy TDD nigdy nie miało dla mnie sensu, a nawet teraz tak nie jest. Wiele funkcji, które napisałem w mojej obecnej roli, odbywa się w mechanizmie podobnym do tego, o którym wspominałeś: w pionowych plasterkach, które dopracowuję, aż zadziałają. Kiedy pełniłem tę starą rolę i nadal często nie wiem, co zrobi mój kod, dopóki go nie napiszę , więc pomysł, żebym mógł napisać testy w celu uruchomienia kodu, właśnie zamierzam napisać. nie ma dla mnie sensu, jest nieporęczna i przede wszystkim strata czasu.
To powiedziawszy, testy są cudownymi i magicznymi rzeczami, które sprawiają, że wszystko jest na świecie . Sprawiają, że kod jest poprawny, zapewniają, że Twoja aplikacja robi to, co myślisz, i ogólnie wszystko jest płynniejsze. Pytanie nie brzmi zatem, czy piszesz testy przed kodowaniem, czy po nim. Pytanie, ile czasu poświęcisz na testowanie. To prawdziwy problem, przynajmniej w moim doświadczeniu w tworzeniu oprogramowania. Testowanie wymaga czasu i pieniędzy, a Ty musisz to robić w ramach sprzecznych interesów.
Tak więc ogólnie zgadzam się z tobą: TDD w praktyce jest nieco niewygodne i kłopotliwe. W tym momencie musisz pamiętać, co działa najlepiej w Twojej obecnej sytuacji . Jeśli piszesz krytyczny kod, po prostu upewnij się, że jest ogólnie testowany. Jeśli masz czas, spróbuj TDD i sprawdź, czy to coś w tym procesie doda.
źródło
Nie mogłem polecić twojego podejścia.
Jeśli zastosuję twoje podejście, będzie to na przykład następujące (dom to aplikacja):
Więc twoje podejście kosztuje dużo czasu i dużo wiedzy, zanim zbuduję dom z twoim podejściem. Lub zajmuje to trochę czasu! Nie jest też dość Dżentelmenem pozwalanie innym testom na pisanie kodu, gdy zmienią się wymagania.
Istnieje więc lepsze podejście bez programowania „prototypu” i rozpoczynania refaktoryzacji. Zamiast programować prototyp „zrób projekt z UML swojej aplikacji w następujący sposób.
Jasne, że takie podejście wymaga również wiedzy w języku UML, ale szybko się uczy. Zmiana nazwy klasy lub poruszanie strzałkami w digramie jest zawsze szybsze niż w IDE. Ale nauka korzystania z ram testowych będzie na początku bardziej wyczerpująca. Najlepszy jest tutaj, aby spojrzeć uruchomić test projektów open source i zobaczyć, jak działają. Ale kiedy masz aplikację testową, następna aplikacja będzie znacznie szybsza. Myślę, że dobrze jest wiedzieć, że wszystko działa dobrze.
Po prostu przegłosowałem te podejścia, ponieważ są one bardzo czasochłonne dla początkujących i wcale nie są dobre. Aby mieć czyste granice między strukturą a zachowaniem, możesz użyć Projektu opartego na Domenie i w sekcji Rozmieść samą domenę za pomocą dwóch pakietów (jeden pakiet o nazwie struktura i drugi nazwany zachowanie). Również dla twoich testów. prosty przykład sprawdź ten przykład napisany w języku Java.
źródło
Czy przetestowałeś ręcznie każdą możliwą gałąź twoich warunków po niewielkiej zmianie? Jak długo trwa pętla sprzężenia zwrotnego podczas ręcznego testowania. Jak blisko jest do pętli sprzężenia zwrotnego z automatycznymi testami.
Zautomatyzowane testy (bez względu na to, czy przeprowadzane są testy w pierwszej kolejności, czy nie), przyspieszają - zapewniając szybszą pętlę zwrotną w kodzie.
Czy na pewno pamiętasz, aby przetestować jakiś warunek ręcznie po sześciu miesiącach - nie mów, że udokumentujesz wszystkie ważne warunki do przetestowania - ponieważ pisanie dokumentacji / komentarza jest równoznaczne z pisaniem testu (dokumentacja wykonywalna)
I znowu: czy podczas refaktoryzacji ręcznie przetestowałeś całą logikę, na którą wpływa refaktoryzacja? Ile czasu zajmuje testowanie zmiany refaktoryzacji? Jeśli refaktoryzacja zepsuje jakiś kod, ile czasu zajmie znalezienie przyczyny przerwania?
Piękny i czysty kod, którym się podobałeś, jest bardzo subiektywny. Twój kod może być dla Ciebie czysty i rozsądny. Najlepszą metodą sprawdzenia, czy Twój kod jest naprawdę czytelny, zrozumiały i testowalny, to testy i recenzje kodu wykonane przez innych programistów.
Twoja droga okazała się bardzo produktywna tylko dlatego, że jesteś programistą pracującym tylko z kodem, i myślę, że dopiero zaczynasz pracę w tym projekcie (Ile lat pracujesz nad tym projektem? 6-8 miesięcy?).
Nadal pamiętasz wszystko, co napisałeś, i możesz rozpoznać przyczynę możliwych problemów. Jestem pewien, że zaczniesz pisać testy od 2-3 lat projektu - ponieważ chcesz mieć pewność, że niczego nie zapomnisz.
źródło
Jeśli nigdy nie popełniasz błędów, tak naprawdę nie potrzebujesz testów. Większość programistów popełnia błędy, ale jeśli nigdy tego nie zrobisz i jesteś pewien, że nigdy nie popełnisz błędów w przyszłości (a ty jesteś jedynym w projekcie), naprawdę nie ma powodu, aby marnować czas na pisanie testów.
Ale twoje rozwiązanie jest w połowie drogi, ponieważ proponujesz pisanie testów przy zmianie kodu, ale jednocześnie twoja metoda zakłada, że nigdy nie popełnisz błędów, decydując, dla których części kodu napisać testy. Działa to tylko wtedy, gdy zawsze doskonale rozumiesz, na które obszary może mieć wpływ zmiana. Myślę, że wielu zwykłych programistów (oczywiście nie ty!) Doświadczyło zmiany, a następnie test gdzieś nieoczekiwanie kończy się niepowodzeniem, ponieważ popełniłeś błąd.
Oczywiście dobra architektura, zasady SOLID itp. Powinny temu zapobiec, ale większość programistów nie jest doskonała i dlatego testy w całym systemie są cenne.
źródło