Jestem deweloperem solo z dość ograniczonym czasowo środowiskiem pracy, w którym czas opracowywania wynosi zwykle od 1 do 4 tygodni na projekt, w zależności od wymagań, pilności lub obu. W danym momencie wykonuję około 3-4 projektów, z których niektóre mają nakładające się na siebie terminy.
Oczekuje się, że ucierpi jakość kodu. Nie mam również formalnych testów; zwykle sprowadza się do przejścia przez system, dopóki się nie zepsuje. W rezultacie znaczna liczba błędów ucieka do produkcji, którą muszę naprawić, a to z kolei opóźnia moje inne projekty.
W tym momencie pojawia się testowanie jednostkowe. Prawidłowe wykonanie powinno ograniczyć błędy, nie mówiąc już o tych, które uciekają do produkcji. Z drugiej strony pisanie testów może zająć sporo czasu, co nie brzmi dobrze w przypadku projektów o ograniczonym czasie, takich jak mój.
Pytanie brzmi: ile różnicy czasu napisałby kod testowany jednostkowo w stosunku do kodu niepoddanego testowi i jak zmienia się ta różnica czasu w miarę rozszerzania zakresu projektu?
źródło
Odpowiedzi:
Im później testujesz, tym więcej kosztuje pisanie testów.
Im dłużej żyje błąd, tym droższe jest jego usunięcie.
Prawo malejących zwrotów gwarantuje, że możesz sprawdzić się w zapomnieniu, próbując upewnić się, że nie ma żadnych błędów.
Budda nauczał mądrości środkowej ścieżki. Testy są dobre. Jest coś takiego, jak zbyt wiele dobrego. Kluczem jest możliwość stwierdzenia, kiedy straciłeś równowagę.
Każdy wiersz kodu, który piszesz bez testów, będzie miał znacznie większe koszty dodania testów później niż gdybyś napisał testy przed napisaniem kodu.
Każda linia kodu bez testów będzie znacznie trudniejsza do debugowania lub przepisania.
Każdy test, który napiszesz, zajmie trochę czasu.
Każdy błąd wymaga czasu na naprawę.
Wierni powiedzą ci, abyś nie pisał ani jednego wiersza kodu bez uprzedniego napisania testu zakończonego niepowodzeniem. Test zapewnia zachowanie, którego oczekujesz. Umożliwia szybką zmianę kodu bez obawy o wpływ na resztę systemu, ponieważ test dowodzi, że zachowanie jest takie samo.
Musisz to wszystko porównać z faktem, że testy nie dodają funkcji. Kod produkcyjny dodaje funkcje. A funkcje są tym, co płacą rachunki.
Pragmatycznie dodaję wszystkie testy, z którymi mogę uciec. Ignoruję komentarze na rzecz oglądania testów. Nie ufam nawet kodowi, który robi to, co myślę, że działa. Ufam testom. Ale jestem znany z rzucania okazjonalnego gradu mary i mam szczęście.
Jednak wielu udanych programistów nie robi TDD. To nie znaczy, że nie testują. Po prostu nie obsesyjnie nalegają, aby każda linia kodu miała zautomatyzowany test. Nawet wujek Bob przyznaje, że nie testuje swojego interfejsu użytkownika. Nalega również, abyś wyprowadził całą logikę z interfejsu użytkownika.
Jako metafora futbolu (czyli futbol amerykański) TDD jest dobrą grą naziemną. Testowanie ręczne tylko tam, gdzie piszesz stos kodu i mam nadzieję, że zadziała, jest grą przejściową. W obu przypadkach możesz być dobry. Twoja kariera nie pozwoli na rozegranie play-off, chyba że możesz zrobić jedno i drugie. Nie sprawi, że superowl będzie, dopóki nie dowiesz się, kiedy wybrać każdego z nich. Ale jeśli potrzebujesz szturchnięcia w określonym kierunku: wezwania urzędników częściej mi się zdarzają, kiedy przechodzę.
Jeśli chcesz wypróbować TDD, gorąco polecam ćwiczenie przed próbą zrobienia tego w pracy. TDD wykonane w połowie, na pół serca i na wpół dupsko, to duży powód, dla którego niektórzy go nie szanują. To jak wlewanie jednej szklanki wody do drugiej. Jeśli nie popełnisz tego i zrobisz to szybko i całkowicie, w końcu ściekasz wodą po całym stole.
źródło
Zgadzam się z resztą odpowiedzi, ale bezpośrednio odpowiadam na pytanie o różnicę czasu .
Roy Osherove w swojej książce The Art of Unit Testing, wydanie drugie, strona 200, przeprowadził studium przypadku wdrażania projektów o podobnej wielkości z podobnymi zespołami (pod względem umiejętności) dla dwóch różnych klientów, w których jeden zespół testował, a drugi nie.
Jego wyniki były takie:
Pod koniec projektu masz mniej czasu i mniej błędów. To oczywiście zależy od tego, jak duży jest projekt.
źródło
Jest tylko jedno badanie, które znam, które badało to w „realnym świecie”: Realizacja poprawy jakości poprzez rozwój oparty na testach: wyniki i doświadczenia czterech zespołów przemysłowych . Wykonanie tego w rozsądny sposób jest drogie, ponieważ zasadniczo oznacza to, że musisz opracować to samo oprogramowanie dwukrotnie (lub najlepiej jeszcze częściej) w podobnych zespołach, a następnie wyrzucić wszystkie oprócz jednego.
Rezultatami badań było wydłużenie czasu rozwoju między 15% –35% (co nie jest niczym w pobliżu wartości 2x, która często jest cytowana przez krytyków TDD) oraz zmniejszenie gęstości defektów przed uwolnieniem z 40% –90% (! ). Należy zauważyć, że wszystkie zespoły nie miały wcześniejszego doświadczenia z TDD, więc można założyć, że wydłużenie czasu można przynajmniej częściowo przypisać uczeniu się, a tym samym pójdzie w dół z czasem, ale nie zostało to ocenione w badaniu.
Zauważ, że to badanie dotyczy TDD, a twoje pytanie dotyczy testów jednostkowych, które są bardzo różne, ale jest to najbliższe, jakie mogłem znaleźć.
źródło
null
, funkcjonalność ponad imperatywem, kontrakty kodu, analiza statyczna, automatyczne refaktoryzowanie, brak kontenerów IoC (ale DI) itp. Założę się o tę wartość testów jednostkowych zmniejszy się (ale nie zniknie).Wykonanie dobrze, rozwijanie za pomocą testów jednostkowych może być szybsze, nawet bez uwzględnienia korzyści z wykrycia dodatkowych błędów.
Faktem jest, że nie jestem wystarczająco dobrym programistą, aby po prostu mój kod działał, gdy tylko się skompiluje. Kiedy piszę / modyfikuję kod, muszę go uruchomić, aby upewnić się, że działa tak, jak myślałem. W jednym projekcie wyglądało to tak:
I oczywiście po tym wszystkim zajęło to zwykle kilka podróży w obie strony.
A co jeśli korzystam z testów jednostkowych? Następnie proces wygląda bardziej jak:
Jest to łatwiejsze i szybsze niż ręczne testowanie aplikacji. Nadal muszę ręcznie uruchomić aplikację (więc nie wyglądam głupio, kiedy oddaję pracę, która tak naprawdę wcale nie działa), ale w przeważającej części już wypracowałem załamania i po prostu jestem weryfikacja w tym momencie. Zazwyczaj robię pętlę jeszcze ściślej, używając programu, który automatycznie uruchamia moje testy po zapisaniu.
Zależy to jednak od pracy w bazie kodu przyjaznego dla testów. Wiele projektów, nawet tych z wieloma testami, utrudnia pisanie testów. Ale jeśli nad tym pracujesz, możesz mieć bazę kodu, którą łatwiej przetestować za pomocą testów automatycznych niż testów ręcznych. Jako bonus, możesz utrzymać zautomatyzowane testy i uruchamiać je, aby uniknąć regresji.
źródło
Mimo że jest już wiele odpowiedzi, są one nieco powtarzalne i chciałbym wybrać inny sposób. Testy jednostkowe są cenne tylko wtedy , gdy zwiększają wartość biznesową . Testowanie w celu testowania (testy trywologiczne lub tautologiczne) lub w celu uzyskania jakiejkolwiek arbitralnej metryki (np. Pokrycia kodu) jest programowaniem kultowym.
Testy są kosztowne, nie tylko w czasie, w którym trzeba je napisać, ale także w konserwacji. Muszą być zsynchronizowane z testowanym kodem, inaczej są bezwartościowe. Nie wspominając o koszcie czasu ich uruchomienia przy każdej zmianie. Nie stanowi to przełomu (ani usprawiedliwienia dla nie robienia naprawdę niezbędnych), ale musi zostać uwzględnione w analizie kosztów i korzyści.
Więc pytanie, które należy zadać, decydując, czy (lub jakiego rodzaju) przetestować funkcję / metodę, zadaj sobie pytanie: „jaką wartość dla użytkownika końcowego tworzę / zabezpieczam za pomocą tego testu?”. Jeśli nie potrafisz odpowiedzieć na to pytanie z góry , wtedy ten test prawdopodobnie nie jest wart kosztów pisania / utrzymania. (lub nie rozumiesz domenę problem, który jest waaaay większy problem niż brak testów).
http://rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf
źródło
To zależy od osoby, a także od złożoności i kształtu kodu, z którym pracujesz.
W przypadku większości projektów pisanie testów jednostkowych oznacza, że wykonuję pracę o około 25% szybciej. Tak, nawet uwzględniając czas na napisanie testów.
Ponieważ faktem jest, że oprogramowanie nie jest wykonywane podczas pisania kodu. Odbywa się to, gdy wysyłasz go do klienta i jest z niego zadowolony. Testy jednostkowe są zdecydowanie najbardziej wydajnym sposobem na wykrycie większości błędów, wyodrębnienie większości błędów na potrzeby debugowania i uzyskanie pewności, że kod jest dobry. Musisz zrobić te rzeczy, tak czy inaczej , więc zrobić je dobrze.
źródło
Problem pogarsza się wraz ze wzrostem wieku projektu: ponieważ za każdym razem, gdy dodajesz nową funkcjonalność i / lub za każdym razem, gdy refaktoryzujesz istniejącą implementację, powinieneś ponownie przetestować to, co wcześniej testowano, aby upewnić się, że nadal działa. Tak więc w przypadku długowiecznego (wieloletniego) projektu może być konieczne nie tylko przetestowanie funkcjonalności, ale ponowne przetestowanie jej 100 razy i więcej. Z tego powodu możesz skorzystać z automatycznych testów. Jednak IMO jest wystarczająco dobry (a nawet lepszy), jeśli są to automatyczne testy systemu, a nie automatyczne testy jednostkowe.
Drugim problemem jest to, że błędy mogą być trudniejsze do znalezienia i naprawienia, jeśli nie zostaną wcześnie wykryte. Na przykład, jeśli w systemie jest błąd i wiem, że działał on idealnie, zanim wprowadziłeś ostatnią zmianę, wtedy skoncentruję swoją uwagę na twojej ostatniej zmianie, aby zobaczyć, jak mogła ona wprowadzić błąd. Ale jeśli nie wiem, czy system działał, zanim wprowadziłeś ostatnią zmianę (ponieważ system nie został odpowiednio przetestowany przed ostatnią zmianą), błąd może być wszędzie.
Powyższe dotyczy szczególnie głębokiego kodu, a mniej płytkiego kodu, np. Dodawania nowych stron internetowych, na których nowe strony raczej nie wpłyną na istniejące strony.
Z mojego doświadczenia byłoby to nie do przyjęcia, więc zadajesz niewłaściwe pytanie. Zamiast pytać, czy testy przyspieszą programowanie, powinieneś zapytać, co sprawi, że programowanie będzie bardziej wolne od błędów.
Lepszym pytaniem może być:
Uczenie się jest procesem dwuetapowym: naucz się robić to wystarczająco dobrze, a następnie naucz się robić to szybciej.
źródło
Niektóre aspekty do rozważenia, niewymienione w innych odpowiedziach.
Podsumowanie
Zaczynając od tdd, trudno jest osiągnąć stan „więcej korzyści niż kosztów”, o ile jesteś w „ograniczonym czasowo środowisku pracy”, zwłaszcza jeśli są „sprytni menedżerowie”, którzy mówią ci „pozbyć się drogiego, bezużytecznego” testowanie rzeczy ”
Uwaga: przez „testowanie jednostkowe” mam na myśli „testowanie modułów w izolacji”.
Uwaga: mam na myśli „test regresji”
źródło
Programiści, podobnie jak ludzie zajmujący się większością zadań, nie doceniają tego, ile czasu zajmuje ich wykonanie. Mając to na uwadze, można poświęcić 10 minut na napisanie testu, ponieważ można było napisać mnóstwo kodu, podczas gdy w rzeczywistości spędziłbyś ten czas na wymyśleniu tej samej nazwy funkcji i parametrów, co podczas testu . To jest scenariusz TDD.
Brak pisania testów jest bardzo podobny do posiadania karty kredytowej; wydajemy więcej lub piszemy więcej kodu. Więcej kodu zawiera więcej błędów.
Zamiast decydować się na całkowite pokrycie kodu lub jego brak, sugeruję skupienie się na krytycznej i skomplikowanej części aplikacji i przeprowadzenie testów. W aplikacji bankowej może to być naliczanie odsetek. Narzędzie diagnostyczne silnika może mieć złożone protokoły kalibracji. Jeśli pracujesz nad projektem, prawdopodobnie wiesz, co to jest i gdzie są błędy.
Zacznij powoli. Zbuduj trochę płynności, zanim osądzisz. Zawsze możesz przestać.
źródło
Od dawna Rada Programistów promuje TDD i inne metodologie testowe, nie przypominam sobie ich argumentów i nie zgadzam się z nimi, ale oto dodatkowe rzeczy do rozważenia, które powinny trochę niuansować:
Powiedziałbym, że testowanie jest dobre, ale upewnij się, że testujesz wcześnie i sprawdzasz, gdzie jest zysk.
źródło
mainTest()
wszystkie moduły testowe nie jest tak trudne.Często pomijaną zaletą TDD jest to, że testy działają jako zabezpieczenie, aby upewnić się, że nie wprowadzasz nowych błędów podczas wprowadzania zmian.
Podejście TDD jest niewątpliwie bardziej czasochłonne, ale na wynos napisz mniej kodu, co oznacza mniej problemów. Wszystkie te dzwonki i gwizdy, które często dołączasz, oczywiście nie znajdą się w bazie kodu.
W filmie Swordfish jest scena, w której jeśli pamięć służy, haker musi pracować z pistoletem przy głowie i być rozproszony ... w przeciwnym razie rozproszony. Chodzi o to, że o wiele łatwiej jest pracować, gdy twoja wolna przestrzeń jest w kodzie i masz czas po swojej stronie, a nie miesiące później, gdy klient krzyczy na ciebie i inne priorytety zostają ściśnięte.
Programiści rozumieją, że późniejsze naprawianie błędów jest droższe, ale odwróć to na głowie. Jeśli możesz otrzymać wynagrodzenie w wysokości 500 USD dziennie za kodowanie sposobu, w jaki piszesz teraz, lub 1000 USD, jeśli napisałeś w sposób TDD, zryjesz rękę osobie składającej 2. ofertę. Im szybciej przestaniesz postrzegać testowanie jako obowiązek i postrzegać go jako oszczędność pieniędzy, tym lepiej.
źródło
Mogę odnieść się do twojego doświadczenia - nasza baza kodu prawie nie miała testów i była w większości niestabilna. Stworzenie czegoś zajęło dosłownie wieki, a naprawianie błędów w produkcjach zabrało cenny czas na nowe funkcje.
W celu częściowego przepisania przysięgałem napisać testy dla wszystkich podstawowych funkcji. Na początku zajęło to znacznie więcej czasu, a moja produktywność znacznie spadła, ale potem moja wydajność była lepsza niż kiedykolwiek wcześniej.
Częścią tej poprawy było to, że miałem mniej błędów produkcyjnych, co z kolei prowadziło do mniejszej liczby przerw -> Miałem lepszą uwagę w danym momencie.
Co więcej, umiejętność samodzielnego testowania ORAZ debugowania kodu naprawdę się opłaca - zestaw testów jest znacznie lepszy niż system, którego nie można debugować inaczej niż przy ręcznej konfiguracji, np. Uruchomienie aplikacji i przejście do ekranu i zrobienie czegoś ... być może kilkadziesiąt razy
Ale zauważ, że na początku występuje spadek wydajności, więc zacznij uczyć się testowania w niektórych projektach, w których presja czasu nie jest już szalona. Spróbuj także uruchomić go w projekcie typu greenfield, testowanie jednostek starszego kodu jest bardzo trudne i pomaga, gdy wiesz, jak wygląda dobry zestaw testów.
źródło
Aby uzupełnić poprzednie odpowiedzi: pamiętaj, że testowanie nie jest celem samym w sobie. Celem przeprowadzania testów jest zachowanie aplikacji zgodnie z oczekiwaniami poprzez ewolucję, w nieoczekiwanych kontekstach itp.
Dlatego pisanie testów nie oznacza udowodnienia wszystkich zachowań wszystkich punktów końcowych bytu. To jest częsty błąd. Wielu programistów uważa, że muszą przetestować wszystkie funkcje / obiekty / metody / właściwości / itp. Prowadzi to do dużego obciążenia pracą oraz szeregu nieistotnych kodów i testów. Takie podejście jest powszechne w dużych projektach, w których większość programistów nie jest świadoma holistycznego zachowania, ale widzi tylko domenę interakcji.
Właściwe podejście w przypadku rzadkich zasobów i testowania jest dość oczywiste i ma zdrowy rozsądek, ale nie jest powszechnie sformalizowane: najpierw zainwestuj w testowanie zasobów programistycznych w funkcje wysokiego poziomu, a następnie stopniowo popadaj w specyficzne cechy . Oznacza to, że w pewnym momencie, jako samotny programista, skupisz się nie tylko na testowaniu jednostkowym, ale także na funkcjonalności / integracji / itp. testowanie i w zależności od zasobów czasowych, stopniowo do głównych funkcji jednostkowych, tak jak planowałbyś i rozważał. Testy na wysokim poziomie dostarczą informacji niezbędnych do rozwiązania testów na niskim poziomie / jednolitych oraz do zaplanowania strategii rozwoju testów zgodnie z posiadanymi zasobami.
Na przykład chciałbyś najpierw przetestować łańcuch przetwarzania jako czarną skrzynkę. Jeśli stwierdzisz, że jeden członek łańcucha zawodzi z powodu zachowania, które nie uwzględniało jakiegoś ekstremalnego warunku, piszesz testy, które gwarantują funkcjonalność nie tylko na tym elemencie, ale także na innych. Potem dostarczasz. W następnym cyklu wykryjesz, że czasami awaria sieci. Więc piszesz testy, które rozwiązują taki problem na modułach, które mogą być podatne na atak. I tak dalej.
źródło