Kiedy nie należy przeprowadzać testu jednostkowego?

138

Pracuję w małej firmie jako programista solo. W rzeczywistości jestem jedynym programistą w firmie. Mam kilka (stosunkowo) dużych projektów, które regularnie napisałem i prowadzę, i żaden z nich nie ma testów na ich wsparcie. Kiedy rozpoczynam nowe projekty, często zastanawiam się, czy powinienem spróbować podejścia TDD. Brzmi jak dobry pomysł, ale szczerze mówiąc, nigdy nie usprawiedliwiam dodatkowej pracy.

Ciężko pracuję, by myśleć przyszłościowo w swoim projekcie. Zdaję sobie sprawę, że z pewnością pewnego dnia inny programista będzie musiał zachować mój kod lub przynajmniej go rozwiązać. Utrzymuję rzeczy tak proste, jak to możliwe, komentuję i dokumentuję rzeczy, które trudno byłoby pojąć. A faktem jest, że projekty te nie są tak duże ani skomplikowane, że przyzwoity programista miałby problemy z ich zrozumieniem.

Wiele przykładów testów, które widziałem, sprowadza się do najdrobniejszych szczegółów, obejmujących wszystkie aspekty kodu. Ponieważ jestem jedynym programistą i jestem bardzo blisko kodu w całym projekcie, znacznie bardziej efektywne jest stosowanie wzorca testowego zapisu i ręcznego zapisu. Uważam również, że wymagania i funkcje zmieniają się na tyle często, że utrzymywanie testów spowodowałoby znaczne obciążenie projektu. Czas, który można by poświęcić na zaspokojenie potrzeb biznesowych.

Tak więc za każdym razem dochodzę do tego samego wniosku. Zwrot z inwestycji jest zbyt niski.

Od czasu do czasu konfiguruję kilka testów, aby upewnić się, że poprawnie napisałem algorytm, na przykład obliczanie liczby lat, które ktoś spędził w firmie na podstawie daty zatrudnienia. Ale z punktu widzenia pokrycia kodu pokryłem około 1% mojego kodu.

Czy w mojej sytuacji nadal znajdowałbyś sposób na regularne przeprowadzanie testów jednostkowych, czy czy mam uzasadnione podstawy, by unikać tego narzutu?

AKTUALIZACJA: Kilka rzeczy o mojej sytuacji, które pominąłem: wszystkie moje projekty to aplikacje internetowe. Aby pokryć cały mój kod, musiałbym użyć automatycznych testów interfejsu użytkownika, i to jest obszar, w którym nadal nie widzę wielkiej przewagi nad testowaniem ręcznym.

Ken Pespisa
źródło
1
Dziękuję wszystkim. Dużo się tu uczę. Kilka rzeczy o mojej sytuacji, które pominąłem: Moje projekty to aplikacje internetowe. Aby pokryć cały mój kod, musiałbym użyć automatycznych testów interfejsu użytkownika, i to jest obszar, w którym nadal nie widzę wielkiej przewagi nad testowaniem ręcznym.
Ken Pespisa,
1
Mamy duży sukces w Transactis dzięki narzędziu do testowania automatyzacji sieci Telerik. Mamy już dziesiątki wcześniejszych ręcznych testów przeglądarki przekonwertowanych na automatyzację. Zautomatyzowane testy są ZNACZNIE szybsze, a także WIELKIE, aby uwidocznić wszelkie problemy z wydajnością witryny.
John Kaster,
2
Widziałem projekt, w którym próbowano zautomatyzować testowanie kompletnych stron internetowych przez przeglądarkę. O ile mogę stwierdzić, nie znalazłem żadnego z setek poważnych błędów, które znaleźliśmy podczas ręcznego testowania, a jego opracowanie i utrzymanie wymagało ogromnej ilości czasu. (Korzystanie z Selenium obsługiwanego przez NUnit). Co gorsza, niektóre testy często psują się z powodu braku problemów z powodu niezgodności przeglądarki i środowiska testowego.
O'Rooney
1
To nie jest tak naprawdę odpowiedź, tylko spostrzeżenie ... twój argument przeciwko testowaniu jednostkowemu, ponieważ „wymagania zmieniają się zbyt często” przypomina mi odwrotny argument, który słyszę tam, gdzie pracuję: „nasze programy są tak statyczne, jaki jest sens testowania to prawie nigdy się nie zmienia! ” ;)
Bane
2
Zautomatyzowane testy interfejsu użytkownika aplikacji sieci web nie są testami jednostkowymi, są zupełnie inną bestią i nie obwiniłbym cię, gdybyś ich nie chciał. Ale cały kod biznesowy powinien znajdować się w wewnętrznej bazie danych i właśnie to powinieneś przetestować.
Nyamiou The Galeanthrope

Odpowiedzi:

84

Wiele przykładów testów, które widziałem, sprowadza się do najdrobniejszych szczegółów, obejmujących wszystkie aspekty kodu.

Więc? Nie musisz wszystkiego testować . Tylko odpowiednie rzeczy.

Ponieważ jestem jedynym programistą i jestem bardzo blisko kodu w całym projekcie, znacznie bardziej efektywne jest stosowanie wzorca testowego zapisu i ręcznego zapisu.

To właściwie fałsz. To nie jest bardziej wydajne. To naprawdę tylko nawyk.

To, co robią inni twórcy solo, to napisanie szkicu lub konspektu, napisanie przypadków testowych, a następnie wypełnienie konturu ostatecznym kodem.

To bardzo, bardzo wydajne.

Uważam również, że wymagania i funkcje zmieniają się na tyle często, że utrzymywanie testów spowodowałoby znaczne obciążenie projektu.

To także fałsz. Testy to nie opór. Zmiany wymagań są przeciągane.

Musisz naprawić testy, aby odzwierciedlić wymagania. Czy to ich drobiazgi, czy wysoki poziom; napisane jako pierwsze lub napisane jako ostatnie.

Kod nie jest wykonywany, dopóki testy nie przejdą. To jedna uniwersalna prawda oprogramowania.

Możesz mieć ograniczony test akceptacyjny „tutaj jest”.

Lub możesz mieć jakieś testy jednostkowe.

Lub możesz mieć oba.

Ale bez względu na to, co robisz, zawsze jest test wykazujący, że oprogramowanie działa.

Sugerowałbym, że odrobina formalności i ładny zestaw narzędzi do testowania jednostek sprawia, że ​​ten test jest o wiele bardziej użyteczny.

S.Lott
źródło
8
Podoba mi się twoje pierwsze stwierdzenie, by przetestować tylko odpowiednie rzeczy. Jeśli chodzi o skuteczność testów ręcznych w porównaniu z testami jednostkowymi, nie wierzę, że moje stwierdzenie jest całkowicie fałszywe, ani twoje stwierdzenie jest całkowicie prawdziwe. Wydaje się, że istnieje równowaga między testowaniem automatycznym a ręcznym w celu osiągnięcia maksymalnej wydajności.
Ken Pespisa,
9
@Ken Pespisa: Przepraszam. Wypiłem Kool-Aid TDD około dwa lata temu (po 30 latach od ostatniego testu). Teraz utknąłem na pierwszej próbie. To sprawiło, że jestem o wiele bardziej produktywny, ponieważ mam mniej myślenia o budowie.
S.Lott,
3
@Ken Pespisa: Nie. W odpowiedziach jest równowaga. Gdybyś zapytał, czy warto podzielić przez zero, uzyskałbyś przytłaczające odpowiedzi pochylone w jedną stronę z jakiegoś powodu. Gdybyś zapytał, czy sqrt(-1)powinna być liczbą całkowitą, uzyskasz przytłaczające odpowiedzi pochylone w jedną stronę. Bilans dotyczy „jak” i „jaki porządek”. Sam fakt jest taki, że musisz przetestować. Więc najpierw napisz testy i upewnij się, że działają.
S.Lott,
21
Rozważ testowanie interfejsu przez jednostkę, a nie szczegóły implementacji. Przetestuj limity i przypadki graniczne. Przetestuj ryzykowny kod. Dużo kodu jest wystarczająco proste do sprawdzenia przez inspekcję, chociaż kontrola kodu jest bardziej podatna na błędy niż kontrola kodu innego użytkownika. Za pierwszym razem testy manualne mogą być bardziej wydajne, a po raz dziesiąty zautomatyzowane testy są już daleko.
BillThor
10
„Kod nie jest gotowy, dopóki testy nie przejdą” - Nie, IMO. Kod zaczyna się po przejściu testów. Kod nie jest tworzony, dopóki nie zostanie uruchomiony przez rok lub dwa i nie został poddany testom warunków skrajnych i testom integracji z dużą, aktywną i niecierpliwą bazą użytkowników. To jedyne testowanie, które naprawdę się liczy.
Wektor
107

Wyobraź sobie, że masz zestaw testów, które można uruchomić w linku do oczu i zapalić zielone lub czerwone światło. Wyobraź sobie, że ten zestaw testów przetestował wszystko ! Wyobraź sobie, że wystarczyło tylko napisać ^ T, aby uruchomić zestaw testów. Jaką moc to by ci dało?

Czy możesz zmienić kod bez obawy, że coś zepsujesz? Czy możesz dodać nową funkcję bez obawy o uszkodzenie starej funkcji? Czy potrafisz szybko wyczyścić niechciany kod bez obawy o uszkodzenie?

Tak, możesz robić te wszystkie rzeczy! A co z czasem stanie się z twoim kodem? Byłoby coraz czystsze, ponieważ nie byłoby ryzyka czyszczenia.

Wyobraźmy sobie, że miałeś małą wróżkę na ramieniu. Za każdym razem, gdy piszesz wiersz kodu, wróżka dodaje coś do zestawu testów, który testuje, że ten wiersz kodu robi to, co powinien. Więc co kilka sekund możesz nacisnąć ^ T i zobaczyć, że ostatni wiersz kodu, który napisałeś, działał.

Jak myślisz, ile debugowania zrobiłbyś?

Jeśli to brzmi jak fantazja, masz rację. Ale rzeczywistość niewiele się różni. Wymień linkę oczną na kilka sekund, a wróżka na dyscyplinę TDD, a już ją masz.

Powiedzmy, że wracasz do systemu zbudowanego rok temu i zapomniałeś, jak stworzyć jeden z centralnych obiektów. Istnieją testy, które tworzą ten obiekt w każdy możliwy sposób. Możesz przeczytać te testy i pobudzić pamięć. Chcesz zadzwonić do API? Istnieją testy, które wywołują ten interfejs API w każdy możliwy sposób. Te testy to małe dokumenty napisane w języku, który rozumiesz. Są całkowicie jednoznaczne. Są tak formalni, że wykonują. I nie mogą się zsynchronizować z aplikacją!

Nie warta inwestycji? Chyba sobie żartujesz! Jak ktokolwiek mógłby NIE chcieć tego zestawu testów? Zrób sobie przysługę i przestań się kłócić o głupotę. Naucz się dobrze robić TDD i patrz, jak szybko jedziesz i jak czystszy jest twój kod.

Wujek Bob.
źródło
28
Wow, Wujek Bob? Wspaniale jest mieć tutaj swoje myśli. Zgadzam się z tobą w sprawie korzyści płynących z TDD, naprawdę nie ma tam żadnych argumentów. Pytanie dotyczy inwestycji czasu i zwrotu z inwestycji. Rozumowanie tych rzeczy nie jest głupie. Wyobraź sobie, że ukończenie projektu z TDD zajmie mi o 50% więcej czasu, a wróżka mówi mi, że pozwoli mi to zaoszczędzić tylko 10% czasu w porównaniu z testowaniem ręcznym w trakcie trwania projektu. To może wydawać się fantazją, ale widzę to jako całkowicie prawdopodobne w przypadku niektórych projektów.
Ken Pespisa,
11
@Ken „Wyobraź sobie, że ukończenie projektu z TDD zajmie mi o 50% więcej czasu niż bez niego”. Dla mnie to brzmi DOKŁADNIE jak fantazja. W rzeczywistości wygląda na to, że właśnie stworzyłeś tę postać na miejscu, bez odrobiny dowodów na jej poparcie.
Rein Henrichs
18
@ Rein Henrichs - Oczywiście, że wymyśliłem ten numer, było to hipotetyczne stwierdzenie. Zwracam uwagę, że TDD dodaje znaczną ilość czasu do projektu i muszę się zastanowić, czy w zamian otrzymam coś o równej lub lepszej wartości. Jestem przekonany, że nie musisz mnie przekonywać o wartościach TDD. Ale to nie jest panaceum.
Ken Pespisa
11
@ Rein, czym dokładnie jest „dostępny dowód?” Proszę opracować.
Ken Pespisa
22
@ Uncle Bob „Zamień linkę oczną na kilka sekund”: Oczywiście żartujesz. TDD jest dobrym narzędziem, ale musisz przetestować tylko odpowiednie części, w przeciwnym razie poświęcisz więcej czasu na utrzymanie testów niż na jakiekolwiek poważne prace rozwojowe. Jest to szczególnie ważne, gdy wymagania zmieniają się bardzo szybko: ciągle piszesz i wyrzucasz testy dla klas, które zmieniają się cały czas. Nie twierdzę, że TDD jest zły, należy go używać rozsądnie i nie stosować mechanicznie, jak się wydaje.
Giorgio,
34

Popełniasz błąd, ponieważ postrzegasz testowanie jako inwestycję czasową bez natychmiastowego zwrotu. To niekoniecznie tak działa.

Po pierwsze, pisanie testów naprawdę koncentruje się na tym, co powinna zrobić ta część kodu.

Po drugie ich uruchomienie ujawnia błędy, które w innym przypadku pojawiałyby się w testach.

Po trzecie, uruchamianie ich czasami pokazuje błędy, które inaczej nie pojawiałyby się w testach, a następnie naprawdę ugryzłyby cię w tyłek podczas produkcji.

Po czwarte, jeśli trafisz błąd w działającym systemie i utworzysz dla niego test jednostkowy, nie będziesz mógł ponownie wprowadzić tego błędu później. To może być naprawdę duża pomoc. Ponownie wprowadzone błędy są powszechne i bardzo denerwujące.

Po piąte, jeśli kiedykolwiek będziesz musiał przekazać kod komuś innemu, pakiet testowy znacznie ułatwi jego życie. Również jeśli zignorujesz projekt i powrócisz do niego po kilku latach, nie będziesz już tak blisko niego, a także będzie ci pomocny.

Moje doświadczenie konsekwentnie polega na tym, że w trakcie opracowywania projektu, posiadanie przyzwoitych testów jednostkowych zawsze czyniło proces szybszym i bardziej niezawodnym.

glenatron
źródło
2
@Ken, zestawy testowe są specyfikacjami w postaci wykonywalnej.
32

Ludzie z JUnit (platforma testowa Java Unit) mają filozofię, że jeśli testowanie jest zbyt proste, nie testuj go . Bardzo polecam przeczytanie często zadawanych pytań dotyczących najlepszych praktyk , ponieważ jest to dość pragmatyczne.

TDD to inny proces pisania oprogramowania. Podstawową przesłanką testów jednostkowych jest to, że będziesz spędzać mniej czasu w debuggerze przechodząc przez kod i szybciej dowiedzieć się, czy zmiana kodu przypadkowo psuje coś innego w systemie. To pasuje do TDD. Cykl TDD wygląda następująco:

  1. Napisz test
  2. Zobacz, jak się nie udaje (udowodnij, że masz coś do zrobienia)
  3. Napisz tylko to, co jest potrzebne do zaliczenia testu - nigdy więcej.
  4. Patrz, jak mija (tak!)
  5. Refaktoryzacja (popraw to)
  6. Umyj, spłucz i powtórz

Mniej oczywiste w zastosowaniu TDD jest to, że zmienia sposób pisania kodu . Zmuszając się do myślenia o tym, jak przetestować / sprawdzić poprawność działania kodu, piszesz testowalny kod. A ponieważ mówimy o testowaniu jednostkowym, zwykle oznacza to, że kod staje się bardziej modułowy. Dla mnie modułowy i testowalny kod to duża wygrana.

Czy musisz teraz przetestować takie właściwości, jak C #? Wyobraź sobie właściwość zdefiniowaną w ten sposób:

bool IsWorthTesting {get; set;}

Odpowiedź brzmiałaby „nie”, nie warto testować, ponieważ w tym momencie testujesz funkcję języka. Ufaj, że faceci z platformy C # mają rację. Poza tym, jeśli nie powiodła się, co mógłby zrobić, aby to naprawić?

Przekonasz się również, że istnieją pewne części twojego kodu, które bardzo dobrze będą wymagały zbyt dużego wysiłku, aby poprawnie przetestować. Oznacza to, że nie rób tego, ale upewnij się, że testujesz kod, który używa / jest używany przez trudny problem:

  • Sprawdzone wyjątki, które mogą wystąpić tylko w przypadku niepowodzenia instalacji. Java ma ich mnóstwo. Musisz napisać blok przechwytujący lub zadeklarować sprawdzony wyjątek, nawet jeśli nie ma możliwości, aby się nie udało bez włamania się do zainstalowanych plików.
  • Interfejsy użytkownika. Znalezienie testowanej kontroli i wywołanie odpowiednich zdarzeń w celu symulacji działań użytkownika jest bardzo kłopotliwe, aw niektórych przypadkach niemożliwe. Jeśli jednak użyjesz wzorca Model / Widok / Kontroler, możesz upewnić się, że Twój model i kontrolery zostały przetestowane i pozostawić część widoku do testowania ręcznego.
  • Interakcje klient / serwer. To nie jest już test jednostkowy, a teraz test integracyjny . Napisz wszystkie części, które idą w górę do wysyłania i odbierania wiadomości za pośrednictwem przewodu, ale tak naprawdę nie przechodź przez przewód. Dobrym podejściem jest zmniejszenie odpowiedzialności za kod, który faktycznie komunikuje się przewodowo do nieprzetworzonej komunikacji. W kodzie testu jednostkowego wykpiwaj obiekt komunikacyjny, aby upewnić się, że usługi działają zgodnie z oczekiwaniami.

Wierz lub nie, TDD pomoże ci wpaść w zrównoważone tempo rozwoju. Nie dzieje się tak z powodu magii, ale raczej dlatego, że masz ścisłą pętlę sprzężenia zwrotnego i jesteś w stanie szybko złapać naprawdę głupie błędy. Koszt naprawienia tych błędów jest zasadniczo stały (przynajmniej wystarczający do celów planowania), ponieważ małe błędy nigdy nie stają się dużymi błędami. Porównaj to z masywną naturą sprintów do usuwania kodu i usuwania błędów.

Berin Loritsch
źródło
24

Musisz zrównoważyć koszt testowania z kosztem błędów.

Pisanie 10-liniowego testu jednostkowego dla funkcji, która otwiera plik, w przypadku niepowodzenia „brak pliku” jest bezcelowe.

Funkcja, która robi coś złożonego ze złożoną strukturą danych - wtedy oczywiście tak.

Podstępny bit znajduje się pomiędzy. Pamiętaj jednak, że prawdziwą wartością testów jednostkowych nie jest testowanie konkretnej funkcji, lecz testowanie trudnych interakcji między nimi. Zatem test jednostkowy, który wykrył zmianę jednego bitu kodu, psuje jakąś funkcję w innym module oddalonym o 1000 linii, jest wart swojej wagi w kawie.

Martin Beckett
źródło
23

Testowanie to hazard.

Utworzenie testu to zakład, że koszt błędów w jednostce, które się pojawią i ich nie złapanie w tym teście (teraz i podczas wszystkich przyszłych poprawek kodu) jest większy niż koszt opracowania testu. Te koszty opracowywania testów obejmują między innymi płacę za dodatkową inżynierię testów, dodatkowy czas wprowadzenia na rynek, utracone koszty alternatywne wynikające z braku kodowania innych rzeczy itp.

Jak każdy zakład, czasami wygrywasz, czasem przegrywasz.

Czasami późne oprogramowanie z znacznie mniejszą liczbą błędów wygrywa z szybkimi, ale błędnymi rzeczami, które trafiają na rynek jako pierwsze. Czasem odwrotnie. Musisz spojrzeć na statystyki w swojej dziedzinie i na ile zarząd chce grać.

Niektóre rodzaje błędów mogą być tak mało prawdopodobne, aby były wykonane, lub nie mogły zostać wykorzystane na wczesnych testach poczytalności, ponieważ statystycznie nie warto poświęcać czasu na tworzenie dodatkowych konkretnych testów. Ale czasami koszt błędu jest tak wielki (medyczny, nuklearny itp.), Że firma musi postawić przegrany zakład (podobnie jak zakup ubezpieczenia). Wiele aplikacji nie wiąże się z tak wysokimi kosztami awarii, a zatem nie potrzebuje wyższej nieekonomicznej ochrony ubezpieczeniowej. Inni tak.

hotpaw2
źródło
3
Dobra odpowiedź. Jedna z niewielu, która naprawdę odpowiada na moje pierwotne pytanie. Pogrążyłem się w świecie testowania od momentu napisania tego postu (lubię go przy okazji). Muszę go lepiej zrozumieć, zanim naprawdę będę wiedział, kiedy go używać (lub nie). Z wielu podanych tutaj powodów wolałbym go używać cały czas. Ale ostatecznie będzie to zależeć od tego, o ile szybciej na tym dojdę, ponieważ w końcu jest to hazard mojego czasu, który jest pod kontrolą mojej firmy / klienta, i często koncentrują się na dolnych rogach trójkąta projektu: en. wikipedia.org/wiki/Projekt_triangle
Ken Pespisa
10

Radzę przetestować tylko kod, który chcesz poprawnie działać.

Nie testuj kodu, który ma być błędem i powodować problemy w przyszłości.

Nick Hodges
źródło
9
Przypomina mi powiedzenie mojego dentysty: Nie musisz nici dentystycznej myć wszystkie zęby, tylko te, które chcesz zachować.
Ken Pespisa,
Przyznaję, że właśnie o tym pomyślałem. ;-)
Nick Hodges
8

Często zastanawiam się, czy powinienem spróbować podejścia TDD. Brzmi jak dobry pomysł, ale szczerze mówiąc, nigdy nie usprawiedliwiam dodatkowej pracy.

TDD i testy jednostkowe to nie to samo.

Możesz napisać kod, a następnie dodać testy jednostkowe później. To nie jest TDD i wymaga dużo dodatkowej pracy.

TDD to praktyka kodowania w pętli czerwonego światła. Zielone światło. Refaktoryzuj iteracje.

Oznacza to pisanie testów dla kodu, który jeszcze nie istnieje, obserwowanie niepowodzenia testów, poprawianie kodu, aby testy działały, a następnie poprawianie kodu. To często oszczędza ci pracy

Jedną z zalet TDD jest to, że zmniejsza potrzebę myślenia o ciekawostkach. Rzeczy, takie jak błędy indywidualne, znikają. Nie musisz przeszukiwać dokumentacji API, aby dowiedzieć się, czy lista, którą zwraca, zaczyna się od 0 lub 1, po prostu zrób to.

Paul Butcher
źródło
Czy mógłbyś wyjaśnić, w jaki sposób znikają błędy indywidualne? Czy mówisz, że możesz szybciej uzyskać odpowiedź na pytanie, czy indeks tablicy jest zerowy czy oparty na testowaniu, niż przeszukiwanie dokumentacji? Wydaje mi się to mało prawdopodobne - jestem dość szybki w Google :)
Ken Pespisa
1
W rzeczywistości pisanie TDD to doskonały sposób na eksplorację API (w tym starszej bazy kodu do celów dokumentowania funkcjonalności).
Frank Shearar
Jest to również bardzo przydatne, jeśli ten interfejs API kiedykolwiek się zmieni ... Nagle masz kilka nieudanych testów :-)
bitsoflogic
@Ken Pespisa, To zdecydowanie szybsze - napisz kod na podstawie tego, czy uważasz, że to 0, czy 1, uruchom go, w razie potrzeby napraw. Przez większość czasu będziesz miał rację i zrezygnowałbyś z konieczności sprawdzenia, jeśli się pomylisz, wiesz o tym w ciągu 10 sekund.
Paul Butcher,
Bardzo interesująca korzyść. Podoba mi się to.
Ken Pespisa,
3

Pracowałem nad systemem, w którym testowaliśmy prawie wszystko. Ważnymi wykonaniami do testowania były kod wyjściowy PDF i XLS.

Dlaczego? Byliśmy w stanie przetestować części, które zgromadziły dane i zbudowaliśmy model, który został użyty do utworzenia danych wyjściowych. Byliśmy również w stanie przetestować części, które wymyśliły, które części modelu przejdą do plików PDF. Nie byliśmy w stanie sprawdzić, czy plik PDF wyglądał dobrze, ponieważ było to całkowicie subiektywne. Nie byliśmy w stanie sprawdzić, czy wszystkie części w pliku PDF były czytelne dla typowego użytkownika, ponieważ było to również subiektywne. Lub jeśli wybór między wykresami słupkowymi i kołowymi był prawidłowy dla zestawu danych.

Jeśli dane wyjściowe będą subiektywne, niewiele jest testów jednostkowych, dzięki czemu można zrobić tyle, ile warto.

sal
źródło
W rzeczywistości tego rodzaju testy to prawdopodobnie „testy integracyjne”. I tak, testy integracyjne są o wiele trudniejsze niż testy jednostkowe, a jednym z powodów jest to, że czasami zasady „poprawności” są bardzo skomplikowane, a nawet subiektywne.
sleske,
2

W wielu przypadkach „test zapisu i ręczny” nie zajmuje więcej czasu niż napisanie kilku testów. Oszczędności czasu wynikają z możliwości ponownego uruchomienia tych testów w dowolnym momencie.

Pomyśl o tym: Jeśli masz jakiś przyzwoity zasięg funkcji ze swoich testów (nie mylić z pokrycia kodu) i powiedzmy masz 10 możliwości - kliknięcie przycisku oznacza, że z grubsza 10 yous wielokrotnego robi swoje badania ... podczas gdy ty siadasz i popijasz kawę.

Także nie ma przetestować minutae. Możesz pisać testy integracyjne, które obejmują twoje funkcje, jeśli nie chcesz zagłębiać się w drobiazgowe szczegóły ... IMO, niektóre testy jednostkowe są zbyt szczegółowe, testując język i platformę, a nie kod.

TL; DR To naprawdę nigdy nie jest właściwe, ponieważ korzyści są po prostu zbyt dobre.

Steven Evers
źródło
2

Dwie bardzo dobre odpowiedzi, na które natrafiłem, są tutaj:

  1. Kiedy test jednostkowy a test ręczny
  2. Czego nie testować, jeśli chodzi o testowanie jednostkowe?

Uzasadnienie unikania postrzeganego narzutu:

  • Natychmiastowa oszczędność czasu / kosztów dla Twojej firmy
  • Potencjalna oszczędność czasu / kosztów w rozwiązywaniu problemów / konserwacji / rozszerzaniu w dłuższej perspektywie, nawet po Twojej nieobecności.

Czy nie chciałbyś zostawić ze swojej strony świetnego produktu jako dowodu jakości swojej pracy? Mówiąc samolubnie, czy nie jest to dla ciebie lepsze?

Aditya P.
źródło
1
Dobre pytanie na końcu. Jestem absolutnie dumny z mojej pracy, a moje aplikacje działają bardzo dobrze (jeśli mogę być tak odważny). Ale masz rację - mogą być jeszcze lepsze dzięki wsparciu niektórych testów. Wydaje mi się, że staram się zmieścić jak najwięcej użytecznych testów w czasie, gdy muszę pracować nad projektem, i nie mam zbytniej obsesji na punkcie pokrycia kodu.
Ken Pespisa,
1

Profesjonalni programiści piszą testy jednostkowe, ponieważ w dłuższej perspektywie oszczędzają czas. Wcześniej czy później zamierzasz przetestować swój kod, a jeśli tego nie zrobią użytkownicy, a jeśli będziesz musiał później naprawić błędy, trudniej będzie je naprawić i będzie miał więcej efektów powalających.

Jeśli piszesz kod bez testów i nie ma błędów, to dobrze. Nie sądzę jednak, aby można było napisać nietrywialny system z zerowymi błędami, więc zakładam, że testujesz go w ten czy inny sposób.

Testy jednostkowe są również niezbędne, aby zapobiec regresjom podczas modyfikacji lub refaktoryzacji starszego kodu. Nie dowodzą, że twoja zmiana nie złamała starego kodu, ale dają ci dużo pewności siebie (o ile oczywiście przejdą :))

Nie wracałbym i nie napisałbym całej partii testów dla kodu, który już wysłałeś, ale następnym razem, gdy będziesz musiał zmodyfikować funkcję, sugeruję, aby spróbować napisać testy dla tego modułu lub klasy, aby uzyskać zasięg do 70% + przed zastosowaniem jakichkolwiek zmian. Sprawdź, czy to ci pomoże.

Jeśli spróbujesz i możesz szczerze powiedzieć, że to nie była pomoc, to wystarczająco uczciwa, ale myślę, że istnieje wystarczająca ilość dowodów branżowych, że pomagają sprawić, by była przynajmniej warta wypróbowania tego podejścia.

Steve
źródło
Lubię przemyślenia na temat zapobiegania regresjom i dodawania pewności siebie. To są dokładnie powody, dla których chciałbym dodać testy.
Ken Pespisa,
1

Wygląda na to, że większość odpowiedzi jest pro-TDD, chociaż pytanie nie dotyczyło TDD, ale ogólnie testów jednostkowych.

Nie ma całkowicie obiektywnej zasady dotyczącej tego, co należy testować, a czego nie. Ale zdarza się, że wielu programistów nie testuje jednostkowo:

  1. Metody prywatne

W zależności od filozofii OOP możesz tworzyć prywatne metody oddzielania złożonych procedur od metod publicznych. Metody publiczne są zwykle przeznaczone do wywoływania w wielu różnych miejscach i często używane, a metody prywatne są tak naprawdę wywoływane tylko przez jedną lub dwie metody publiczne w klasie lub module, aby uzyskać coś bardzo konkretnego. Zwykle wystarczy napisać testy jednostkowe dla metod publicznych, ale nie podstawowe metody prywatne, które powodują magię. Jeśli coś pójdzie nie tak z metodą prywatną, publiczne testy jednostkowe metody powinny być wystarczająco dobre, aby wykryć te problemy.

  1. Rzeczy, które już wiesz, powinny działać (lub rzeczy przetestowane przez kogoś innego)

Wielu nowych programistów sprzeciwia się temu, kiedy uczą się najpierw testować i myślą, że muszą przetestować każdą wykonywaną linię. Jeśli korzystasz z zewnętrznej biblioteki, a jej funkcjonalność jest dobrze przetestowana i udokumentowana przez jej autorów, zwykle nie ma sensu testować konkretnej funkcjonalności w testach jednostkowych. Na przykład ktoś może napisać test, aby upewnić się, że jego model ActiveRecord utrzymuje poprawną wartość atrybutu z wywołaniem zwrotnym „before_save” do bazy danych, nawet jeśli samo to zachowanie jest już dokładnie przetestowane w Railsach. Metoda może wywoływać funkcję zwrotną, ale nie samo zachowanie wywołania zwrotnego. Wszelkie podstawowe problemy z importowanymi bibliotekami lepiej byłoby ujawnić za pomocą testów akceptacyjnych niż testów jednostkowych.

Oba mogą mieć zastosowanie niezależnie od tego, czy robisz TDD, czy nie.

Krukon
źródło
0

Ken, ja i wielu innych programistów doszliśmy do tego samego wniosku co ty kilka razy w ciągu naszej kariery.

Prawda, którą, jak sądzę, znajdziesz (podobnie jak wiele innych), jest taka, że ​​początkowa inwestycja w pisanie testów dla twojej aplikacji może wydawać się zniechęcająca, ale jeśli dobrze napisana i ukierunkowana na właściwe części twojego kodu, może naprawdę zaoszczędzić mnóstwo czasu.

Moim wielkim problemem były dostępne ramy testowe. Nigdy tak naprawdę nie czułem, że są tym, czego szukałem, więc właśnie opracowałem własne bardzo proste rozwiązanie. To naprawdę pomogło mi przenieść się na „ciemną stronę” testów regresji. Podzielę się podstawowym pseudo fragmentem tego, co tutaj zrobiłem, i mam nadzieję, że znajdziesz rozwiązanie, które będzie dla ciebie odpowiednie.

public interface ITest {
    public string Name {
        get;
    }
    public string Description {
        get;
    }
    public List<ITest> SubTests {
        get;
    }
    public TestResult Execute();
}

public class TestResult {
    public bool Succesful {
        get;
        set;
    }

    public string ResultMessage {
        get;
        set;
    }

    private Dictionary<ITest, TestResult> subTestResults = new Dictionary<ITest, TestResult>();
    public Dictionary<ITest, TestResult> SubTestResults {
        get {
            return subTestResults;
        }
        set {
            subTestResults = value;
        }
    }
}

Jedyną trudną częścią po tym jest ustalenie, jaki poziom szczegółowości uważasz za najlepszy „huk za grosze” dla każdego projektu.

Zbudowanie książki adresowej będzie oczywiście wymagało znacznie mniej testów niż wyszukiwarka korporacyjna, ale podstawy tak naprawdę się nie zmieniają.

Powodzenia!

Adam Carstensen
źródło
Z czasem zastanowię się, jaki poziom szczegółowości jest najlepszy. Dobrze jest usłyszeć od innych osób, które regularnie tworzą testy, że podchodzą do niego rozsądnie i nie robią automatycznie testów dla każdego możliwego wyniku. Moje pierwsze wprowadzenie do testów było na poziomie, na którym wszystko musi być przetestowane. W rzeczywistości cała koncepcja TDD wydaje się podążać za tą mantrą.
Ken Pespisa,
Myślę, że możesz skorzystać z frameworka takiego jak SubSpec (zainspirowany przez BDD), który pozwoli ci uzyskać izolację Assert („SubTest”) podczas udostępniania konfiguracji kontekstu.
Johannes Rudolph