Załóżmy, że mamy dużą aplikację na poziomie przedsiębiorstwa bez żadnych testów jednostkowych / funkcjonalnych. W trakcie opracowywania nie było procesu programowania opartego na testach z powodu bardzo napiętych terminów (wiem, że nigdy nie powinniśmy obiecać żadnych napiętych terminów, gdy nie jesteśmy pewni, ale to, co zostało zrobione, zostało zrobione!)
Teraz, gdy minęły wszystkie terminy i wszystko jest spokojne, wszyscy zgodzili się przekształcić nas w produktywny zespół oparty na TDD / BDD ... Tak!
Teraz pytanie dotyczy kodu, który już mamy: (1) Czy nadal jest w porządku, czy dobrym pomysłem jest zatrzymanie większości prac rozwojowych i rozpoczęcie pisania całych możliwych przypadków testowych od samego początku, nawet jeśli wszystko działa całkowicie OK? (Jeszcze!) ? Lub (2) lepiej poczekać, aż wydarzy się coś złego, a następnie podczas naprawy napisz nowe testy jednostkowe, lub (3) nawet zapomnij o poprzednich kodach i po prostu napisz testy jednostkowe tylko dla nowych kodów i odłóż wszystko do następnego dużego refaktora.
Istnieje kilka dobrych i powiązanych artykułów, takich jak ten . Nadal nie jestem pewien, czy warto w to zainwestować, biorąc pod uwagę, że mamy bardzo ograniczony czas i czeka na nas wiele innych projektów / prac.
Uwaga : To pytanie wyjaśnia / wyobraża sobie całkowicie niezręczną sytuację w zespole programistów. Tu nie chodzi o mnie ani o żadnego z moich kolegów; to tylko wyimaginowana sytuacja. Możesz myśleć, że to nigdy nie powinno się zdarzyć, lub kierownik ds. Rozwoju jest odpowiedzialny za taki bałagan! Ale i tak to, co się stało, zostało zrobione. Jeśli to możliwe, proszę nie głosować tylko dlatego, że uważasz, że to nigdy nie powinno się zdarzyć.
źródło
int
wartość i zwróci coś konkretnego, nie jest możliwe napisanie testu jednostkowego dla każdej możliwejint
wartości, ale prawdopodobnie warto przetestować garść użytecznych wartości, które mogą spowodować zadziałanie kod, taki jak liczby ujemne (w tymminint
), zeromaxint
itp., aby upewnić się, że niektóre przypadki brzegowe są uwzględnione.Odpowiedzi:
To stwierdzenie jest bardzo niepokojące. Nie dlatego, że oznacza to, że opracowałeś bez TDD, albo dlatego, że nie testujesz wszystkiego. Jest to niepokojące, ponieważ pokazuje, że uważasz, że TDD spowolni cię i sprawi, że nie dotrzymasz terminu.
Tak długo, jak widzisz to w ten sposób, nie jesteś gotowy na TDD. TDD nie jest czymś, w co można stopniowo się ulżyć. Albo wiesz, jak to zrobić, albo nie. Jeśli spróbujesz to zrobić w połowie, sprawisz, że będziesz wyglądać źle.
TDD jest czymś, co powinieneś najpierw ćwiczyć w domu. Naucz się tego robić, ponieważ pomaga to teraz kodować . Nie dlatego, że ktoś kazał ci to zrobić. Nie dlatego, że pomoże to później wprowadzić zmiany. Kiedy staje się to czymś, co robisz, ponieważ się spieszysz, jesteś gotowy zrobić to profesjonalnie.
TDD to coś, co możesz zrobić w każdym sklepie. Nie musisz nawet oddawać kodu testowego. Możesz zachować to dla siebie, jeśli inni gardzą testami. Jeśli zrobisz to dobrze, testy przyspieszą Twój rozwój, nawet jeśli nikt inny ich nie uruchomi.
Z drugiej strony, jeśli inni uwielbiają i przeprowadzają twoje testy, powinieneś pamiętać, że nawet w sklepie TDD sprawdzanie testów nie jest twoim zadaniem. Ma na celu stworzenie sprawdzonego działającego kodu produkcyjnego. Jeśli zdarza się, że można to przetestować, nieźle.
Jeśli uważasz, że kierownictwo musi wierzyć w TDD lub że inni koderzy muszą wspierać twoje testy, to ignorujesz najlepszą rzecz, jaką TDD dla Ciebie robi. Szybko pokazuje różnicę między tym, co myślisz, że robi twój kod, a tym, co faktycznie robi.
Jeśli nie widzisz, jak to samo w sobie może pomóc Ci szybciej dotrzymać terminu, oznacza to, że nie jesteś gotowy na TDD w pracy. Musisz ćwiczyć w domu.
To powiedziawszy, miło jest, gdy zespół może użyć twoich testów, aby pomóc im odczytać twój kod produkcyjny, i kiedy kierownictwo kupi nowe narzędzia TDD.
Niezależnie od tego, co robi zespół, nie zawsze dobrym pomysłem jest napisanie wszystkich możliwych przypadków testowych. Napisz najbardziej przydatne przypadki testowe. 100% pokrycia kodu kosztuje. Nie ignoruj prawa zmniejszania się zysków tylko dlatego, że trudno jest dokonać osądu.
Oszczędzaj energię na testowanie, aby uzyskać interesującą logikę biznesową. Rzeczy, które podejmują decyzje i egzekwują zasady. Sprawdź, do diabła z tego. Nudny, łatwy do odczytania kod kleju strukturalnego, który po prostu łączy ze sobą elementy, nie wymaga tak samo testowania.
Nie. To jest myślenie „zróbmy kompletne przepisanie”. To niszczy ciężko zdobytą wiedzę. Nie proś kierownictwa o czas na napisanie testów. Po prostu napisz testy. Gdy dowiesz się, co robisz, testy Cię nie spowolnią.
Odpowiem 2 i 3 w ten sam sposób. Kiedy zmieniasz kod, z jakiegokolwiek powodu, naprawdę fajnie jest, jeśli możesz wpaść w test. Jeśli kod jest starszej wersji, obecnie nie przyjmuje testu. Co oznacza, że trudno go przetestować przed zmianą. Cóż, skoro i tak to zmieniasz, możesz zmienić to na coś do przetestowania i przetestować.
To jest opcja nuklearna. To ryzykowne. Wprowadzasz zmiany bez testów. Istnieje kilka kreatywnych sztuczek, aby przetestować starszy kod przed jego zmianą. Szukasz tak zwanych szwów, które pozwalają zmienić zachowanie kodu bez zmiany kodu. Zmieniasz pliki konfiguracyjne, budujesz pliki, cokolwiek trzeba.
Michael Feathers dał nam książkę na ten temat: Skuteczna praca ze starszym kodem . Przeczytaj to, a zobaczysz, że nie musisz spalać wszystkiego, co stare, aby stworzyć coś nowego.
źródło
Biorąc pod uwagę starszy kod 1 , napisz testy jednostkowe w następujących sytuacjach:
Choć przydatne są testy jednostkowe, stworzenie kompletnego pakietu testów jednostkowych dla istniejącej 1 bazy kodu prawdopodobnie nie jest realistycznym pomysłem. Moce, które zmusiły cię do dotrzymania napiętego terminu. Nie dały ci czasu na stworzenie odpowiednich testów jednostkowych w miarę rozwoju. Czy uważasz, że dadzą ci wystarczająco dużo czasu na przygotowanie testów dla „programu, który działa”?
1 Starszy kod to kod bez testów jednostkowych. To jest definicja TDD starszego kodu. Ma to zastosowanie nawet wtedy, gdy starszy kod jest świeżo dostarczony [nawet jeśli atrament jeszcze nie wyschł].
źródło
Z mojego doświadczenia wynika, że testy nie potrzebują pełnego zasięgu, aby były pomocne. Zamiast tego zaczniesz czerpać różne korzyści w miarę wzrostu zasięgu:
Prawda jest taka, że jeśli nie zaczynasz od BDD, nigdy tam nie dojdziesz, ponieważ praca wymagana do przetestowania po kodowaniu jest po prostu nadmierna. Problemem nie jest pisanie testów, ale przede wszystkim świadomość rzeczywistych wymagań (a nie przypadkowych szczegółów implementacyjnych) i możliwość zaprojektowania oprogramowania w sposób zarówno funkcjonalny, jak i łatwy do przetestowania. Kiedy piszesz testy najpierw lub razem z kodem, jest to praktycznie darmowe.
Ponieważ nowe funkcje wymagają testów, ale testy wymagają zmian w projekcie, ale refaktoryzacja również wymaga testów, masz problem z kurczakiem i jajami. Gdy twoje oprogramowanie zbliża się do przyzwoitego zasięgu, będziesz musiał ostrożnie przefiltrować te części kodu, w których pojawiają się nowe funkcje, tylko po to, aby nowe funkcje mogły zostać przetestowane. Spowoduje to bardzo spowolnienie - początkowo. Ale tylko poprzez refaktoryzację i testowanie tych części, w których potrzebny jest nowy rozwój, testy koncentrują się również na tym obszarze, w którym są najbardziej potrzebne. Stabilny kod może być kontynuowany bez testów: gdyby był błędny, i tak musiałbyś go zmienić.
Podczas próby dostosowania się do TDD lepszym miernikiem niż całkowity zasięg projektu byłby zasięg testowy w zmienianych częściach. Zakres ten powinien być bardzo wysoki od samego początku, choć nie jest możliwe przetestowanie wszystkich części kodu, na które wpływa refaktoryzacja. Ponadto czerpiesz większość korzyści z wysokiego pokrycia testowego w testowanych komponentach. To nie jest idealne, ale wciąż dość dobre.
Należy pamiętać, że chociaż testy jednostkowe wydają się być powszechne, rozpoczynanie od najmniejszych elementów nie jest odpowiednią strategią do testowania starszego oprogramowania. Będziesz chciał rozpocząć od testów integracyjnych, które wykonują jednocześnie dużą część oprogramowania.
Np. Uznałem, że użyteczne jest wyodrębnienie przypadków testowych integracji z logów rzeczywistych. Oczywiście przeprowadzanie takich testów może zająć dużo czasu, dlatego warto skonfigurować zautomatyzowany serwer, który regularnie uruchamia testy (np. Serwer Jenkins uruchamiany przez commits). Koszt założenia i utrzymania takiego serwera jest bardzo mały w porównaniu z regularnym uruchamianiem testów, pod warunkiem, że wszelkie niepowodzenia testów zostaną naprawione szybko.
źródło
Nie pisz testów dla istniejącego kodu. To nie jest tego warte.
To, co stworzyłeś, jest już nieco przetestowane w całkowicie nieformalny sposób - ciągle wypróbowywałeś je ręcznie, ludzie przeprowadzali testy nieautomatyczne, jest teraz używany. Oznacza to, że nie znajdziesz wielu błędów .
Pozostały błędy, o których nie pomyślałeś. Ale są to dokładnie te, dla których nie pomyślisz o napisaniu testów jednostkowych, więc prawdopodobnie nadal ich nie znajdziesz.
Powodem TDD jest też zastanowienie się, jakie są dokładne wymagania odrobiny kodu przed jego napisaniem. W inny sposób już to zrobiłeś.
Tymczasem napisanie tych testów jest tak samo dużo, jak byłoby napisanie ich wcześniej. Będzie to kosztowało dużo czasu, bez korzyści.
Bardzo nudne jest pisanie wielu testów bez kodowania pomiędzy nimi i nie znajdowanie prawie żadnych błędów. Jeśli zaczniesz to robić, ludzie nowi w TDD będą go nienawidzić .
Krótko mówiąc, deweloperzy będą go nienawidzić, a menedżerowie uznają to za kosztowne, podczas gdy nie znaleziono wielu błędów. Nigdy nie dojdziesz do faktycznej części TDD.
Używaj go do rzeczy, które chcesz zmienić, jako normalnej części procesu.
źródło
Test jest środkiem do komunikowania zrozumienia.
Dlatego pisz tylko testy dla tego, co rozumiesz, powinno być prawdą.
Możesz zrozumieć, co powinno być prawdą, kiedy z nim pracujesz.
Dlatego pisz tylko testy dla kodu, z którym pracujesz.
Podczas pracy z kodem nauczysz się.
Dlatego pisz i przepisz testy, aby uchwycić to, czego się nauczyłeś.
Wypłukać i powtórzyć.
Uruchom narzędzie do pokrywania kodu wraz z testami i akceptuj tylko zatwierdzenia do linii głównej, które nie zmniejszają zasięgu. W końcu osiągniesz wysoki poziom zasięgu.
Jeśli od jakiegoś czasu nie pracowałeś z kodem, musisz podjąć decyzję biznesową. Jest to prawdopodobnie tak spuścizna, że nikt z twojego zespołu nie wie, jak z tym pracować. Prawdopodobnie ma nieaktualne biblioteki / kompilatory / dokumentację, co jest ogromną odpowiedzialnością pod każdym względem.
Dwie opcje:
źródło
Jednym z głównych celów testów jest upewnienie się, że zmiana niczego nie zepsuła. Jest to trzyetapowy proces:
Oznacza to, że musisz mieć sprawne testy, zanim faktycznie coś zmienisz. Jeśli wybierzesz drugą ścieżkę, oznacza to, że będziesz musiał zmusić programistów do napisania testów, zanim dotkną kodu. I mocno podejrzewam, że już w obliczu zmiany w świecie rzeczywistym programiści nie zamierzają poświęcać testom urządzeń uwagi, na jaką zasługują.
Sugeruję więc podzielenie zadań pisania testów i wprowadzania zmian, aby deweloperzy nie poświęcali jakości jednego z nich dla drugiego.
Aby to podkreślić, powszechne jest błędne przekonanie, że potrzebujesz testów tylko wtedy, gdy kod nie działa. Potrzebujesz również testów, gdy kod również działa, na przykład, aby udowodnić komuś, że [nowo pojawiający się błąd] nie jest spowodowany twoją częścią, ponieważ testy wciąż przechodzą.
Potwierdzenie, że wszystko nadal działa tak, jak poprzednio, jest ważną zaletą testowania, którego pomijasz, gdy sugerujesz, że nie potrzebujesz testów, gdy kod działa.
Idealnie byłoby, gdyby cały istniejący kod źródłowy otrzymał teraz testy jednostkowe. Istnieje jednak uzasadniony argument, że czas i wysiłek (i koszty) potrzebne do tego po prostu nie mają znaczenia w przypadku niektórych projektów.
Na przykład aplikacje, które nie są już opracowywane i nie oczekuje się, że zostaną zmienione (np. Klient już go nie używa lub klient nie jest już klientem), możesz argumentować, że testowanie tego kodu nie jest już istotne .
Jednak nie jest tak wyraźne cięcie w miejscu, w którym rysujesz linię. Jest to coś, na co firma musi spojrzeć w analizie kosztów i korzyści. Pisanie testów kosztuje czas i wysiłek, ale czy spodziewają się dalszego rozwoju tej aplikacji? Czy korzyści z posiadania testów jednostkowych przewyższają koszty ich pisania?
To nie jest decyzja, którą możesz podjąć (jako programista). W najlepszym wypadku możesz podać szacunkowy czas potrzebny na wdrożenie testów dla danego projektu, a to do kierownictwa należy decyzja, czy istnieje wystarczające oczekiwanie na utrzymanie / rozwój projektu.
Jeśli podany jest następny duży refaktor, to naprawdę musisz napisać testy.
Ale nie odkładaj tego, dopóki nie napotkasz poważnych zmian. Mój początkowy punkt (nie łącząc pisanie testów i uaktualniania kodu) nadal stoi, ale chcę dodać drugi punkt tutaj: programiści obecnie poznać ich sposób wokół projektu lepiej niż oni będą w ciągu sześciu miesięcy, jeśli spędzają ten czas pracy na inne projekty. Wykorzystaj okresy, w których programiści są już rozgrzani i nie musisz wymyślać, jak wszystko będzie działać w przyszłości.
źródło
Moje dwa centy:
Poczekaj na ważną aktualizację techniczną systemu i napisz testy, a następnie ... oficjalnie przy wsparciu firmy.
Alternatywnie, powiedzmy, że jesteś sklepem SCRUM, twoje obciążenie pracą jest reprezentowane przez pojemność i możesz przeznaczyć% tego na testy jednostkowe, ale ...
Mówienie, że wrócisz i napiszesz testy, jest naiwne, tak naprawdę musisz napisać testy, refaktoryzować i napisać więcej testów po tym, jak refaktor sprawi, że kod będzie bardziej testowalny, dlatego najlepiej zacząć z testami, jak już wiesz, i ...
Dla autora oryginalnego najlepiej jest napisać testy i zmodyfikować kod, który napisali wcześniej, nie jest to idealne, ale z doświadczenia chcesz, aby refaktor poprawił kod, a nie gorzej.
źródło