Zdecydowanie rozważam dodanie testów jednostkowych do istniejącego projektu, który jest w produkcji. Zaczęło się 18 miesięcy temu, zanim naprawdę mogłem dostrzec jakąkolwiek korzyść z TDD (dłoń twarzowa) , więc teraz jest to dość duże rozwiązanie z wieloma projektami i nie mam najmniejszego pojęcia, od czego zacząć dodawanie testów jednostkowych. To sprawia, że zastanawiam się nad tym, że czasami wydaje się, że stary błąd pojawia się ponownie lub błąd jest sprawdzany jako naprawiony, ale tak naprawdę nie jest naprawiany. Testowanie jednostkowe zmniejszyłoby lub zapobiegłoby występowaniu tych problemów.
Czytając podobne pytania na temat SO, zobaczyłem zalecenia, takie jak rozpoczęcie od śledzenia błędów i napisanie przypadku testowego dla każdego błędu, aby zapobiec regresji. Obawiam się jednak, że przeoczę ogólny obraz i przeoczę podstawowe testy, które zostałyby uwzględnione, gdybym używał TDD od samego początku.
Czy są jakieś procesy / kroki, których należy przestrzegać, aby zapewnić, że istniejące rozwiązania są właściwie testowane jednostkowo, a nie tylko wprowadzane? Jak mogę zapewnić, że testy są dobrej jakości i nie są tylko przypadkiem jakiegokolwiek testu, jest lepsze niż brak testów .
Więc myślę, że to, o co też proszę, to;
- Czy warto podjąć wysiłek dla istniejącego rozwiązania, które jest w produkcji?
- Czy lepiej byłoby zignorować testy dla tego projektu i dodać je w możliwym przyszłym przepisaniu?
- Co będzie bardziej korzystne; spędzasz kilka tygodni na dodawaniu testów lub kilka tygodni na dodawaniu funkcjonalności?
(Oczywiście odpowiedź na trzeci punkt zależy całkowicie od tego, czy rozmawiasz z kierownictwem, czy z programistą)
Powód Bounty
Dodanie nagrody, aby spróbować przyciągnąć szerszą gamę odpowiedzi, które nie tylko potwierdzają moje obecne podejrzenie, że jest to dobra rzecz, ale także kilka dobrych powodów przeciw.
Zamierzam napisać to pytanie później z zaletami i wadami, aby spróbować pokazać kierownictwu, że warto poświęcić godziny na przeniesienie przyszłego rozwoju produktu na TDD. Chcę podejść do tego wyzwania i rozwinąć swoje rozumowanie bez własnego, stronniczego punktu widzenia.
źródło
Odpowiedzi:
Wprowadziłem testy jednostkowe do baz kodu, które wcześniej go nie miały. Ostatni duży projekt, w którym byłem zaangażowany, kiedy to zrobiłem, produkt był już w produkcji z zerowymi testami jednostkowymi, kiedy dotarłem do zespołu. Kiedy odszedłem - 2 lata później - mieliśmy około 4500+ testów dających około 33% pokrycia kodu w bazie kodu z 230 000 + produkcyjnym LOC (finansowa aplikacja Win-Forms w czasie rzeczywistym). Może to zabrzmieć nisko, ale rezultatem była znaczna poprawa jakości kodu i wskaźnika defektów oraz poprawa morale i rentowności.
Można to zrobić, mając zarówno dokładne zrozumienie, jak i zaangażowanie zaangażowanych stron.
Przede wszystkim ważne jest, aby zrozumieć, że testowanie jednostkowe jest umiejętnością samą w sobie. Możesz być bardzo produktywnym programistą według „konwencjonalnych” standardów i nadal mieć trudności z napisaniem testów jednostkowych w sposób, który skaluje się w większym projekcie.
Ponadto, szczególnie w danej sytuacji, dodawanie testów jednostkowych do istniejącej bazy kodu, która nie ma testów, jest również specjalistyczną umiejętnością samą w sobie. O ile ty lub ktoś z twojego zespołu nie ma pomyślnego doświadczenia we wprowadzaniu testów jednostkowych do istniejącej bazy kodu, powiedziałbym, że przeczytanie książki Feather jest wymogiem (nie jest opcjonalne ani zdecydowanie zalecane).
Przejście na testowanie jednostkowe kodu jest inwestycją w ludzi i umiejętności, tak samo jak w jakość kodu. Zrozumienie tego jest bardzo ważne z punktu widzenia nastawienia i zarządzania oczekiwaniami.
Teraz, jeśli chodzi o komentarze i pytania:
Krótka odpowiedź: Tak, przegapisz testy i tak, początkowo mogą nie wyglądać tak, jak miałyby w sytuacji green field.
Bardziej szczegółowa odpowiedź brzmi: to nie ma znaczenia. Zaczynasz bez testów. Zacznij dodawać testy i refaktoryzuj w miarę postępów. Wraz ze wzrostem poziomu umiejętności zacznij podnosić poprzeczkę dla całego nowo napisanego kodu dodanego do projektu. Kontynuuj ulepszanie itp ...
Teraz, czytając między wierszami, odnoszę wrażenie, że wynika to z myślenia o „doskonałości jako wymówce dla niepodejmowania działań”. Lepszym sposobem myślenia jest skupienie się na zaufaniu do siebie. Ponieważ możesz jeszcze nie wiedzieć, jak to zrobić, zorientujesz się, jak to zrobić, i wypełnisz puste pola. Dlatego nie ma powodu do zmartwień.
Ponownie, to umiejętność. Nie można przejść od testów zerowych do doskonałości TDD w jednym „procesie” lub „krok po kroku” podejściu do książki kucharskiej w sposób liniowy. To będzie proces. Twoje oczekiwania muszą dotyczyć stopniowego i narastającego postępu i poprawy. Nie ma magicznej pigułki.
Dobra wiadomość jest taka, że wraz z upływem miesięcy (a nawet lat) Twój kod będzie stopniowo stawał się „prawidłowym”, dobrze podzielonym na czynniki i dobrze przetestowanym kodem.
Na marginesie. Przekonasz się, że główną przeszkodą we wprowadzaniu testów jednostkowych w starej bazie kodu jest brak spójności i nadmierne zależności. Dlatego prawdopodobnie okaże się, że najważniejszą umiejętnością będzie przełamywanie istniejących zależności i oddzielanie kodu, zamiast samodzielnego pisania rzeczywistych testów jednostkowych.
Jeśli jeszcze go nie masz, skonfiguruj serwer kompilacji i skonfiguruj kompilację ciągłej integracji, która działa przy każdym sprawdzaniu, w tym wszystkich testach jednostkowych z pokryciem kodu.
Szkol swoich ludzi.
Zacznij gdzieś i zacznij dodawać testy, robiąc postępy z perspektywy klienta (patrz poniżej).
Użyj pokrycia kodu jako przewodniego odniesienia do tego, jaka część kodu produkcyjnego jest testowana.
Czas budowy powinien być zawsze szybki. Jeśli czas kompilacji jest wolny, twoje umiejętności testowania jednostkowego są opóźnione. Znajdź wolne testy i popraw je (oddziel kod produkcyjny i testuj w izolacji). Dobrze napisane, powinieneś być w stanie łatwo przeprowadzić kilka tysięcy testów jednostkowych i nadal ukończyć kompilację w mniej niż 10 minut (~ 1-kilka ms / test to dobra, ale bardzo przybliżona wskazówka, kilka wyjątków może mieć zastosowanie, jak kod wykorzystujący odbicie itp. ).
Sprawdź i dostosuj.
Twój własny osąd musi być głównym źródłem rzeczywistości. Nie ma miernika, który mógłby zastąpić umiejętności.
Jeśli nie masz takiego doświadczenia lub osądu, rozważ zatrudnienie kogoś, kto to robi.
Dwa ogólne wskaźniki pomocnicze to całkowite pokrycie kodu i szybkość kompilacji.
Tak. Zdecydowana większość pieniędzy wydanych na niestandardowy system lub rozwiązanie jest wydawana po wprowadzeniu go do produkcji. Inwestowanie w jakość, ludzi i umiejętności nigdy nie powinno wychodzić z mody.
Musiałbyś wziąć pod uwagę nie tylko inwestycję w ludzi i umiejętności, ale przede wszystkim całkowity koszt posiadania i spodziewany czas życia systemu.
Moja osobista odpowiedź brzmiałaby „tak, oczywiście” w większości przypadków, ponieważ wiem, że jest o wiele lepiej, ale zdaję sobie sprawę, że mogą być wyjątki.
Ani. Twoje podejście powinno polegać na dodawaniu testów do bazy kodu, GDY robisz postęp w zakresie funkcjonalności.
Ponownie, jest to inwestycja w ludzi, umiejętności ORAZ jakość bazy kodu i jako taka będzie wymagała czasu. Członkowie zespołu muszą nauczyć się, jak przełamywać zależności, pisać testy jednostkowe, uczyć się nowych nawyków, poprawiać dyscyplinę i świadomość jakości, jak lepiej projektować oprogramowanie itp. Ważne jest, aby zrozumieć, że kiedy zaczynasz dodawać testy, członkowie zespołu prawdopodobnie tego nie zrobią. mają te umiejętności na wymaganym poziomie, aby to podejście odniosło sukces, więc zatrzymywanie postępów w celu spędzenia całego czasu na dodaniu wielu testów po prostu nie zadziała.
Ponadto dodawanie testów jednostkowych do istniejącej bazy kodu o dowolnej wielkości projektu jest DUŻYM przedsięwzięciem, które wymaga zaangażowania i wytrwałości. Nie możesz zmienić czegoś fundamentalnego, spodziewaj się po drodze dużej wiedzy i poproś swojego sponsora, aby nie oczekiwał zwrotu z inwestycji poprzez zatrzymanie przepływu wartości biznesowej. To nie poleci i szczerze mówiąc nie powinno.
Po trzecie, chcesz zaszczepić w swoim zespole solidne wartości biznesowe. Jakość nigdy nie odbywa się kosztem klienta, a bez jakości nie można działać szybko. Ponadto klient żyje w zmieniającym się świecie, a Twoim zadaniem jest ułatwienie mu adaptacji. Dostosowanie do klienta wymaga zarówno jakości, jak i przepływu wartości biznesowej.
To, co robisz, to spłacanie długu technicznego. Robisz to, jednocześnie obsługując stale zmieniające się potrzeby klientów. Stopniowo, gdy dług jest spłacany, sytuacja poprawia się i łatwiej jest lepiej obsługiwać klienta i dostarczać więcej wartości. Itd. Ten pozytywny rozmach jest tym, do czego powinieneś dążyć, ponieważ podkreśla on zasady zrównoważonego tempa i utrzyma i poprawi moralność - zarówno dla zespołu programistów, klienta, jak i interesariuszy.
Mam nadzieję, że to pomoże
źródło
Tak!
Nie!
Dodanie testów (zwłaszcza testów automatycznych) znacznie ułatwia utrzymanie projektu w przyszłości i znacznie zmniejsza prawdopodobieństwo, że dostarczysz użytkownikowi głupie problemy.
Testy, które należy umieścić a priori, to te, które sprawdzają, czy według Ciebie publiczny interfejs twojego kodu (i każdego modułu w nim zawartego) działa tak, jak myślisz. Jeśli możesz, spróbuj również wywołać każdy tryb awarii izolowanej, który powinien mieć twoje moduły kodu (pamiętaj, że może to być nietrywialne i powinieneś uważać, aby nie sprawdzać zbyt dokładnie, jak coś zawodzi, np. Naprawdę nie chcesz na przykład zliczanie komunikatów dziennika generowanych w przypadku awarii, ponieważ wystarczy zweryfikować, czy w ogóle są zarejestrowane).
Następnie przeprowadź test dla każdego aktualnego błędu w bazie danych błędów, który wywołuje dokładnie błąd i który przejdzie, gdy błąd zostanie naprawiony. Następnie napraw te błędy! :-)
Dodanie testów kosztuje z góry czas, ale otrzymujesz zwrot pieniędzy wiele razy na zapleczu, ponieważ kod kończy się o wiele wyższej jakości. Ma to ogromne znaczenie, gdy próbujesz wysłać nową wersję lub przeprowadzić konserwację.
źródło
Problem z modernizacją testów jednostkowych polega na tym, że zdasz sobie sprawę, że nie pomyślałeś o wstrzyknięciu zależności tutaj lub użyciu tam interfejsu, a wkrótce będziesz przepisać cały komponent. Jeśli masz na to czas, zbudujesz sobie ładną siatkę bezpieczeństwa, ale po drodze mogłeś wprowadzić subtelne błędy.
Byłem zaangażowany w wiele projektów, które naprawdę wymagały testów jednostkowych od pierwszego dnia i nie ma łatwego sposobu na ich wprowadzenie, poza całkowitym przepisaniem, co zwykle nie może być uzasadnione, gdy kod działa i już zarabia. Ostatnio uciekłem się do pisania skryptów PowerShell, które ćwiczą kod w sposób, który odtwarza defekt, gdy tylko zostanie on zgłoszony, a następnie zachowuje te skrypty jako zestaw testów regresji w celu dalszych zmian. W ten sposób możesz przynajmniej zacząć budować kilka testów dla aplikacji bez zbytniej zmiany jej, jednak są to bardziej testy regresji typu end-to-end niż właściwe testy jednostkowe.
źródło
Zgadzam się z tym, co powiedział większość innych. Dodanie testów do istniejącego kodu jest cenne. Nigdy nie zgodzę się z tym punktem, ale chciałbym dodać jedno zastrzeżenie.
Chociaż dodawanie testów do istniejącego kodu jest cenne, wiąże się to z kosztami. Jest to kosztem braku tworzenia nowych funkcji. To, jak te dwie rzeczy się równoważą, zależy całkowicie od projektu i istnieje wiele zmiennych.
Ponownie, podkreślę, testy są cenne i powinieneś popracować nad przetestowaniem starego kodu. To bardziej zależy od tego, jak do tego podejdziesz. Jeśli możesz sobie pozwolić na porzucenie wszystkiego i przetestowanie całego starego kodu, zrób to. Jeśli to nie jest realistyczne, oto co powinieneś zrobić przynajmniej
Nie jest to również propozycja „wszystko albo nic”. Jeśli masz zespół składający się, powiedzmy, z czterech osób i możesz dotrzymać terminów, zlecając jedną lub dwie osoby na dotychczasowe obowiązki testowe, zrób to.
Edytować:
To jak pytanie „Jakie są wady i zalety korzystania z kontroli źródła?” lub „Jakie są wady i zalety przeprowadzania wywiadów z ludźmi przed ich zatrudnieniem?” lub „Jakie są wady i zalety oddychania?”
Czasami jest tylko jedna strona sporu. Musisz mieć zautomatyzowane testy w jakiejś formie dla każdego projektu o dowolnej złożoności. Nie, testy nie piszą się same i tak, zajmie trochę więcej czasu, zanim wszystko wyjdzie na jaw. Ale na dłuższą metę naprawienie błędów po fakcie zajmie więcej czasu i będzie kosztować więcej pieniędzy niż napisanie testów z góry. Kropka. To wszystko.
źródło
Kiedy zaczęliśmy dodawać testy, był to dziesięcioletni kod, zawierający około miliona linii, ze zbyt dużą logiką w interfejsie użytkownika i kodzie raportowania.
Jedną z pierwszych rzeczy, które zrobiliśmy (po skonfigurowaniu serwera ciągłej kompilacji) było dodanie testów regresji. To były testy od początku do końca.
Celem testów regresji jest stwierdzenie, czy coś się zmieni. Oznacza to, że zawodzą, jeśli coś zepsułeś, ale również zawodzą, jeśli coś zmieniłeś celowo (w takim przypadku poprawka polega na zaktualizowaniu pliku migawki). Nie wiesz, że pliki migawek są nawet poprawne - w systemie mogą być błędy (a następnie, gdy naprawisz te błędy, testy regresji zakończą się niepowodzeniem).
Niemniej jednak testy regresji były dla nas ogromną wygraną. Prawie wszystko w naszym systemie ma raport, więc spędzając kilka tygodni na testowaniu raportów, byliśmy w stanie uzyskać pewien poziom pokrycia w dużej części naszej bazy kodu. Napisanie równoważnych testów jednostkowych zajęłoby miesiące lub lata. (Testy jednostkowe zapewniłyby nam znacznie lepsze pokrycie i byłyby znacznie mniej kruche, ale wolałbym mieć coś teraz, zamiast czekać latami na doskonałość).
Następnie wróciliśmy i zaczęliśmy dodawać testy jednostkowe, gdy naprawialiśmy błędy, dodawaliśmy ulepszenia lub potrzebowaliśmy zrozumieć kod. Testy regresji w żaden sposób nie eliminują potrzeby testów jednostkowych; są tylko siatką bezpieczeństwa pierwszego poziomu, dzięki czemu szybko uzyskasz pewien poziom pokrycia testu. Następnie możesz rozpocząć refaktoryzację w celu zerwania zależności, dzięki czemu możesz dodać testy jednostkowe; a testy regresji dają pewność, że refaktoryzacja niczego nie psuje.
Testy regresyjne mają problemy: są powolne i istnieje zbyt wiele powodów, dla których mogą się zepsuć. Ale przynajmniej dla nas były tego warte. W ciągu ostatnich pięciu lat złapali niezliczone błędy i złapali je w ciągu kilku godzin, zamiast czekać na cykl kontroli jakości. Wciąż mamy te oryginalne testy regresyjne, rozłożone na siedem różnych maszyn z ciągłą kompilacją (oddzielnych od tej, która wykonuje szybkie testy jednostkowe), a nawet dodajemy do nich od czasu do czasu, ponieważ wciąż mamy tyle kodu, że nasze 6000 + testy jednostkowe nie obejmują.
źródło
To jest absolutnie tego warte. Nasza aplikacja ma złożone reguły weryfikacji krzyżowej, a ostatnio musieliśmy wprowadzić istotne zmiany w regułach biznesowych. Skończyło się na konfliktach, które uniemożliwiły użytkownikowi zapisywanie. Zdałem sobie sprawę, że rozwiązanie tego problemu w aplikacji zajmie wieczność (wystarczy kilka minut, aby dojść do punktu, w którym wystąpiły problemy). Chciałem wprowadzić zautomatyzowane testy jednostkowe i miałem zainstalowany framework, ale nie zrobiłem nic poza kilkoma testami pozorowanymi, aby upewnić się, że wszystko działa. Mając w ręku nowe zasady biznesowe, zacząłem pisać testy. Testy szybko zidentyfikowały warunki, które spowodowały konflikty, i udało nam się wyjaśnić zasady.
Jeśli napiszesz testy obejmujące funkcje, które dodajesz lub modyfikujesz, uzyskasz natychmiastowe korzyści. Jeśli czekasz na przepisanie, możesz nigdy nie mieć testów automatycznych.
Nie powinieneś spędzać dużo czasu na pisaniu testów istniejących rzeczy, które już działają. W większości przypadków nie masz specyfikacji istniejącego kodu, więc najważniejszą rzeczą, którą testujesz, jest umiejętność inżynierii wstecznej. Z drugiej strony, jeśli zamierzasz coś zmodyfikować, musisz pokryć tę funkcjonalność testami, aby wiedzieć, że zmiany zostały wprowadzone poprawnie. Oczywiście dla nowej funkcjonalności napisz testy, które kończą się niepowodzeniem, a następnie zaimplementuj brakującą funkcjonalność.
źródło
Dodam swój głos i powiem tak, zawsze się przyda!
Jest jednak kilka różnic, o których należy pamiętać: czarna skrzynka vs biała skrzynka oraz jednostka vs funkcjonalność. Ponieważ definicje są różne, oto, co mam na myśli:
Kiedy dodałem testy do dostarczanego produktu w późnej fazie gry, stwierdziłem, że uzyskałem najwięcej korzyści z testów białej skrzynki i testów funkcjonalnych . Jeśli jakakolwiek część kodu, o której wiesz, jest szczególnie delikatna, napisz testy białoskrzynkowe, aby omówić przypadki problemów, aby upewnić się, że nie psuje się dwa razy w ten sam sposób. Podobnie testy funkcjonalne całego systemu są użyteczną metodą sprawdzania poprawności, która pomaga upewnić się, że nigdy nie złamiesz 10 najczęstszych przypadków użycia.
Przydatne są również testy czarnoskrzynkowe i testy jednostkowe małych jednostek, ale jeśli masz ograniczony czas, lepiej dodać je wcześniej. Przed wysyłką na ogół znalazłeś (na własnej skórze) większość skrajnych przypadków i problemów, które wykryłyby te testy.
Podobnie jak inni przypomnę Ci dwie najważniejsze rzeczy dotyczące TDD:
źródło
To, czy warto dodawać testy jednostkowe do aplikacji, która jest w produkcji, zależy od kosztu utrzymania aplikacji. Jeśli aplikacja zawiera kilka błędów i próśb o ulepszenia, być może nie jest to warte wysiłku. OTOH, jeśli aplikacja zawiera błędy lub jest często modyfikowana, testy jednostkowe będą bardzo korzystne.
W tym miejscu pamiętaj, że mówię o dodawaniu testów jednostkowych w sposób selektywny, a nie o generowaniu zestawu testów podobnych do tych, które istniałyby, gdybyś ćwiczył TDD od początku. Dlatego w odpowiedzi na drugą połowę twojego drugiego pytania: zwróć uwagę na użycie TDD w następnym projekcie, niezależnie od tego, czy jest to nowy projekt, czy przepisanie (przepraszam, ale tutaj jest link do innej książki, którą naprawdę powinieneś przeczytać : Rozwijające się oprogramowanie zorientowane obiektowo na podstawie testów )
Moja odpowiedź na twoje trzecie pytanie jest taka sama jak na pierwsze: zależy to od kontekstu twojego projektu.
W Twoim poście osadzone jest kolejne pytanie dotyczące upewnienia się, że wszelkie testy modernizacji zostały wykonane prawidłowo . Ważne jest, aby upewnić się, że testy jednostkowe naprawdę są testami jednostkowymi , a to (częściej niż nie) oznacza, że modernizacja testów wymaga refaktoryzacji istniejącego kodu, aby umożliwić rozdzielenie warstw / komponentów (por. Iniekcja zależności; odwrócenie kontroli; stubbing; kpiny). Jeśli tego nie wymusisz, testy staną się testami integracyjnymi, które są przydatne, ale mniej ukierunkowane i bardziej kruche niż prawdziwe testy jednostkowe.
źródło
Nie wspominasz o języku implementacji, ale w Javie możesz wypróbować następujące podejście:
W osobnym drzewie źródłowym zbuduj testy regresji lub „dymu”, używając narzędzia do ich generowania, co może zapewnić pokrycie prawie 80%. Te testy wykonują wszystkie ścieżki logiki kodu i od tego momentu sprawdzają, czy kod nadal robi dokładnie to, co obecnie (nawet jeśli występuje błąd). Daje to zabezpieczenie przed nieumyślną zmianą zachowania podczas przeprowadzania niezbędnej refaktoryzacji, aby kod był łatwy do ręcznego testowania jednostkowego.
Dla każdego błędu, który naprawisz lub dodanej funkcji od teraz, użyj podejścia TDD, aby upewnić się, że nowy kod jest zaprojektowany tak, aby był testowalny i umieść te testy w normalnym drzewie testów.
Istniejący kod będzie prawdopodobnie wymagał zmiany lub refaktoryzacji, aby był możliwy do przetestowania w ramach dodawania nowych funkcji; Twoje testy dymu zapewnią Ci ochronę przed regresją lub niezamierzonymi, subtelnymi zmianami w zachowaniu.
Podczas wprowadzania zmian (poprawek błędów lub funkcji) za pośrednictwem TDD, po zakończeniu prawdopodobnie test dymu towarzyszącego kończy się niepowodzeniem. Sprawdź, czy awarie są zgodne z oczekiwaniami z powodu wprowadzonych zmian i usuń mniej czytelny test dymny, ponieważ Twój odręczny test jednostkowy obejmuje cały ulepszony element. Upewnij się, że pokrycie testu nie spada, tylko pozostaje na tym samym poziomie lub wzrasta.
Podczas naprawiania błędów napisz zakończony niepowodzeniem test jednostkowy, który jako pierwszy ujawnia błąd.
źródło
Chciałbym rozpocząć tę odpowiedź od stwierdzenia, że testowanie jednostkowe jest naprawdę ważne, ponieważ pomoże Ci zatrzymać błędy, zanim wkroczą do produkcji.
Zidentyfikuj obszary projektów / modułów, w których ponownie wprowadzono błędy. zacznij od tych projektów, aby napisać testy. Bardzo sensowne jest pisanie testów pod kątem nowej funkcjonalności i poprawiania błędów.
Tak. Zobaczysz efekt schodzenia błędów i łatwiejszą konserwację
Poleciłbym zacząć od teraz.
Zadajesz złe pytanie. Zdecydowanie funkcjonalność jest ważniejsza niż cokolwiek innego. Ale raczej powinieneś zapytać, czy spędzenie kilku tygodni na dodaniu testu sprawi, że mój system będzie bardziej stabilny. Czy pomoże to mojemu użytkownikowi końcowemu? Czy pomoże to nowemu programistowi w zespole zrozumieć projekt, a także upewnić się, że nie wprowadzi błędu z powodu braku zrozumienia ogólnego wpływu zmiany.
źródło
Bardzo lubię Refactor the Low-wiszący owoc jako odpowiedź na pytanie, od czego zacząć refaktoryzację. To sposób na łatwiejsze projektowanie bez odgryzania więcej niż możesz przeżuć.
Myślę, że ta sama logika odnosi się do TDD - lub po prostu testów jednostkowych: napisz testy, których potrzebujesz, tak jak ich potrzebujesz; pisać testy dla nowego kodu; pisz testy pod kątem pojawiających się błędów. Martwisz się, że zaniedbasz trudniej dostępne obszary bazy kodu i na pewno jest to ryzyko, ale jako sposób na rozpoczęcie: zacznij! Możesz zmniejszyć ryzyko w przyszłości za pomocą narzędzi do pokrywania kodu, a ryzyko nie jest (moim zdaniem) tak duże: jeśli pokrywasz błędy, opisujesz nowy kod, obejmujesz kod, na który patrzysz , to omawiasz kod, który ma największe zapotrzebowanie na testy.
źródło
źródło
Tak, to możliwe: po prostu spróbuj się upewnić, że cały kod, który piszesz, ma teraz test.
Jeśli kod, który już istnieje, wymaga modyfikacji i można go przetestować, zrób to, ale lepiej nie być zbyt energicznym w próbach wprowadzenia testów dla stabilnego kodu. Takie rzeczy mają zwykle efekt domina i mogą wymknąć się spod kontroli.
źródło
źródło
Aktualizacja
6 lat po pierwotnej odpowiedzi mam nieco inne podejście.
Myślę, że sensowne jest dodawanie testów jednostkowych do całego nowego kodu, który piszesz - a następnie refaktoryzacja miejsc, w których wprowadzasz zmiany, aby były testowalne.
Pisanie testów za jednym razem dla całego istniejącego kodu nie pomoże - ale nie pisanie testów dla nowego kodu, który piszesz (lub obszarów, które modyfikujesz) również nie ma sensu. Dodawanie testów podczas refaktoryzacji / dodawania elementów jest prawdopodobnie najlepszym sposobem na dodanie testów i uczynienie kodu łatwiejszym w utrzymaniu w istniejącym projekcie bez testów.
Wcześniejsza odpowiedź
Mam zamiar unieść kilka brwi :)
Po pierwsze, jaki jest twój projekt - jeśli jest to kompilator, język, framework lub cokolwiek innego, co nie zmieni funkcjonalnie przez długi czas, to myślę, że dodawanie testów jednostkowych jest absolutnie fantastyczne.
Jeśli jednak pracujesz nad aplikacją, która prawdopodobnie będzie wymagać zmian w funkcjonalności (ze względu na zmieniające się wymagania), nie ma sensu podejmować dodatkowego wysiłku.
Czemu?
Testy jednostkowe obejmują tylko testy kodu - niezależnie od tego, czy kod robi to, do czego jest przeznaczony - nie zastępuje testów ręcznych, które i tak trzeba wykonać (aby odkryć błędy funkcjonalne, problemy z użytecznością i wszystkie inne rodzaje problemów)
Testy jednostkowe kosztują czas! Skąd pochodzę, to cenny towar - a biznes generalnie wybiera lepszą funkcjonalność niż kompletny zestaw testów.
Jeśli Twoja aplikacja jest nawet zdalnie użyteczna dla użytkowników, będą żądać zmian - więc będziesz mieć wersje, które będą robić rzeczy lepiej, szybciej i prawdopodobnie będą robić nowe rzeczy - może być również wiele refaktoryzacji w miarę rozwoju kodu. Utrzymywanie w pełni rozwiniętego zestawu testów jednostkowych w dynamicznym środowisku to ból głowy.
Testy jednostkowe nie wpłyną na postrzeganą jakość Twojego produktu - jakość, którą widzi użytkownik. Jasne, Twoje metody mogą działać dokładnie tak samo, jak pierwszego dnia, interfejs między warstwą prezentacji a warstwą biznesową może być nieskazitelny - ale wiecie co? Użytkownik się tym nie przejmuje! Skorzystaj z pomocy prawdziwych testerów, którzy przetestują Twoją aplikację. I najczęściej te metody i interfejsy i tak muszą się zmienić, wcześniej czy później.
Co będzie bardziej korzystne; spędzasz kilka tygodni na dodawaniu testów lub kilka tygodni na dodawaniu funkcjonalności? - Jest piekło wiele rzeczy, które można zrobić lepiej niż pisanie testów - Pisanie nowych funkcji, zwiększanie wydajności, zwiększanie użyteczności, pisanie lepszych podręczników pomocy, rozwiązywanie oczekujących błędów itp.
Nie zrozum mnie źle - jeśli jesteś absolutnie przekonany, że nic się nie zmieni przez następne 100 lat, śmiało, ogłusz się i napisz te testy. Testy automatyczne to również świetny pomysł dla interfejsów API, w których absolutnie nie chcesz łamać kodu stron trzecich. Wszędzie indziej jest to po prostu coś, co sprawia, że wysyłam później!
źródło
Jest mało prawdopodobne, że kiedykolwiek będziesz mieć znaczący zakres testów, więc musisz taktycznie określać, gdzie dodajesz testy:
OTOH, nie warto po prostu siedzieć i pisać testów wokół kodu, z którego ludzie są zadowoleni - zwłaszcza jeśli nikt nie zamierza go modyfikować. Po prostu nie dodaje wartości (może poza zrozumieniem zachowania systemu).
Powodzenia!
źródło
Mówisz, że nie chcesz kupować kolejnej książki. Przeczytaj więc artykuł Michaela Feathera o efektywnej pracy ze starszym kodem . Następnie kup książkę :)
źródło
Gdybym był na twoim miejscu, prawdopodobnie wybrałbym podejście zewnętrzne, zaczynając od testów funkcjonalnych, które sprawdzają cały system. Chciałbym ponownie udokumentować wymagania systemowe przy użyciu języka specyfikacji BDD, takiego jak RSpec, a następnie napisać testy, aby zweryfikować te wymagania poprzez automatyzację interfejsu użytkownika.
Następnie wykonywałbym programowanie oparte na defektach dla nowo odkrytych błędów, pisząc testy jednostkowe w celu odtworzenia problemów i pracowałem nad błędami, dopóki testy nie przejdą.
W przypadku nowych funkcji pozostałbym przy podejściu z zewnątrz: zacznij od funkcji udokumentowanych w RSpec i zweryfikowanych przez zautomatyzowanie interfejsu użytkownika (co oczywiście początkowo zakończy się niepowodzeniem), a następnie dodaj bardziej szczegółowe testy jednostkowe w miarę postępu implementacji.
Nie jestem ekspertem w tym procesie, ale z niewielkiego doświadczenia, jakie mam, mogę powiedzieć, że BDD za pomocą automatycznego testowania interfejsu użytkownika nie jest łatwe, ale myślę, że jest to warte wysiłku i prawdopodobnie przyniosłoby najwięcej korzyści w twoim przypadku.
źródło
W żadnym wypadku nie jestem doświadczonym ekspertem w dziedzinie TDD, ale oczywiście powiedziałbym, że niezwykle ważne jest testowanie jednostkowe tak dużo, jak tylko możesz. Ponieważ kod jest już na miejscu, zacząłbym od wprowadzenia jakiejś automatyzacji testów jednostkowych. Używam TeamCity do wykonywania wszystkich testów w moich projektach i daje to ładne podsumowanie tego, jak wypadły komponenty.
Mając to na miejscu, przejdę do tych naprawdę krytycznych komponentów podobnych do logiki biznesowej, które nie mogą zawieść. W moim przypadku jest kilka podstawowych problemów z trygometrią, które należy rozwiązać dla różnych danych wejściowych, więc testuję je do cholery. Powodem, dla którego to robię, jest to, że kiedy spalam olej o północy, bardzo łatwo jest tracić czas na kopanie w głąb kodu, którego naprawdę nie trzeba dotykać, ponieważ wiesz, że są testowane pod kątem wszystkich możliwych wejść (w moim przypadku jest skończona liczba wejść).
Ok, więc mam nadzieję, że teraz czujesz się lepiej z tymi krytycznymi fragmentami. Zamiast siadać i walić w wszystkie testy, atakowałbym je, gdy się pojawiały. Jeśli trafisz na błąd, który jest prawdziwym PITA do naprawienia, napisz dla niego testy jednostkowe i usuń je z drogi.
Są przypadki, w których okaże się, że testowanie jest trudne, ponieważ nie możesz utworzyć instancji określonej klasy z testu, więc musisz z niej kpić. Och, ale może nie możesz łatwo z tego kpić, ponieważ nie napisałeś do interfejsu. Traktuję te scenariusze „ups” jako okazję do zaimplementowania wspomnianego interfejsu, ponieważ to dobra rzecz.
Stamtąd dostałbym twój serwer kompilacji lub jakąkolwiek automatyzację, którą masz skonfigurowaną za pomocą narzędzia do pokrycia kodu. Tworzą paskudne wykresy słupkowe z dużymi czerwonymi strefami, w których masz słabe pokrycie. Teraz 100% pokrycia nie jest twoim celem, ani też 100% pokrycia niekoniecznie oznaczałoby, że twój kod jest kuloodporny, ale czerwony pasek zdecydowanie motywuje mnie, gdy mam wolny czas. :)
źródło
Jest tak wiele dobrych odpowiedzi, że nie będę ich powtarzać. Sprawdziłem Twój profil i wygląda na to, że jesteś programistą C # .NET. Z tego powodu dodaję odniesienie do projektu Microsoft PEX i Moles , które mogą pomóc w automatycznym generowaniu testów jednostkowych dla starszego kodu. Wiem, że autogeneracja nie jest najlepszym sposobem, ale przynajmniej jest sposobem na rozpoczęcie. Sprawdź ten bardzo interesujący artykuł z magazynu MSDN o używaniu PEX do starszego kodu .
źródło
Proponuję przeczytać genialny artykuł inżyniera TopTal, który wyjaśnia, od czego zacząć dodawać testy: zawiera dużo matematyki, ale podstawowa idea to:
1) Zmierz łączenie aferentne kodu (CA) (ile klasa jest używana przez inne klasy, co oznacza, że złamanie jej spowodowałoby rozległe szkody)
2) Zmierz złożoność cyklomatyczną (CC) swojego kodu (wyższa złożoność = wyższa zmiana łamania)
Czemu? Ponieważ wysoki poziom CA, ale bardzo niskie klasy CC są bardzo ważne, ale mało prawdopodobne, aby się zepsuły. Z drugiej strony, niski CA, ale wysoki CC prawdopodobnie się zepsuje, ale spowoduje mniej szkód. Więc chcesz zrównoważyć.
źródło
To zależy ...
Wspaniale jest mieć testy jednostkowe, ale musisz wziąć pod uwagę, kim są Twoi użytkownicy i co są skłonni tolerować, aby uzyskać produkt bardziej wolny od błędów. Nieuchronnie przez refaktoryzację kodu, który obecnie nie ma testów jednostkowych, wprowadzisz błędy i wielu użytkownikom będzie trudno zrozumieć, że tymczasowo sprawiasz, że produkt jest bardziej wadliwy, aby na dłuższą metę był mniej wadliwy. Ostatecznie to użytkownicy będą mieli ostatnie słowo ...
źródło
Tak. Nie. Dodawanie testów.
Podejście w kierunku bardziej TDD będzie w rzeczywistości lepiej informować o wysiłkach zmierzających do dodania nowej funkcjonalności i znacznie ułatwi testowanie regresji. Sprawdź to!
źródło