Czy kiedykolwiek dodałeś testy jednostkowe po fakcie do starszego kodu? Jak skomplikowany był kod i jak trudno wszystko odgiąć i wyszydzić? Czy efekt końcowy był wart zachodu?
Czy kiedykolwiek dodałeś testy jednostkowe po fakcie do starszego kodu? Jak skomplikowany był kod i jak trudno wszystko odgiąć i wyszydzić? Czy efekt końcowy był wart zachodu?
Odpowiedzi:
Najlepszym sposobem, jaki znalazłem, jest przyrostowe dodawanie testów jednostkowych, a nie po prostu wskakiwanie i mówienie, że teraz będziemy testować jednostkowo aplikację.
Tak więc, jeśli zamierzasz dotknąć kodu, w celu usunięcia błędów lub refaktoryzacji, najpierw napisz testy jednostkowe. W przypadku błędów testy jednostkowe pomogą udowodnić, gdzie jest problem, ponieważ można go powielić.
W przypadku refaktoryzacji będziesz chciał napisać testy jednostkowe, ale może się okazać, że testu nie da się napisać, więc może zajść potrzeba znalezienia wysokiego poziomu, który wywoła funkcję, która zostanie refaktoryzowana, i przetestuj tę część. Następnie, podczas refaktoryzacji funkcji ofensywnej, napisz testy, aby upewnić się, że działa tak, jak powinno.
Nie ma na to prostego sposobu.
To pytanie może pomóc w uzyskaniu dalszych sugestii. Jak wprowadzić testy jednostkowe do dużej, starszej (C / C ++) bazy kodu?
Książka Michaela Feathersa „Efektywna praca z dotychczasowym kodem” to cała książka na ten temat. Michael stwierdza, że wprowadzenie testów dla starszego kodu jest często zbyt trudne, ponieważ nie ma on struktury umożliwiającej testowanie. To, co najbardziej wyciągnąłem z książki, to kilka wzorców nazwanych „Funkcje kiełkowania” i „Klasy kiełkowania”. Funkcja kiełkowania to taka, która zawiera zmiany, które musisz wprowadzić w kodzie. Następnie testujesz jednostkowo tylko te funkcje. Klasa kiełków to ten sam pomysł, ale nowa funkcjonalność jest zawarta w klasie.
Tak, i ogólnie jest to bolesne. Często musiałem zamiast tego pisać testy integracyjne.
Książka The Art of Unit Testing zawiera kilka dobrych rad na ten temat. Zaleca również książkę „ Skuteczna praca z dotychczasowym kodem” ; Nie przeczytałem jeszcze tego ostatniego, ale jest na moim stosie.
EDYCJA: Ale tak, nawet minimalne pokrycie kodu było warte zachodu. Dało mi to pewność siebie i zabezpieczenie przed refaktoryzacją kodu.
EDYCJA: Przeczytałem Praca efektywnie ze starym kodem i jest doskonała.
Przyjrzyj się także nowemu podejściu w obszarze testowania jednostkowego starszego kodu - projekt Asis , jest inspirowany przez ApprovalTests projektem i dzieli się jego kluczowymi koncepcjami.
Jak wspomniano o podejściu ApprovalTests w tym artykule :
Często masz ogromny, starszy projekt kodu, w którym nie masz żadnych testów, ale musisz zmienić kod, aby zaimplementować nową funkcję lub refaktoryzację. Ciekawą rzeczą w starym kodzie jest to, że działa! Działa przez lata, bez względu na to, jak jest napisane. I to jest bardzo duża zaleta tego kodu. Dzięki zatwierdzeniom za pomocą tylko jednego testu możesz uzyskać wszystkie możliwe wyniki (HTML, XML, JSON, SQL lub cokolwiek to może być) i zatwierdzić, ponieważ wiesz - to działa! Po ukończeniu takiego testu i zatwierdzeniu wyniku, jesteś naprawdę dużo bezpieczniejszy z refaktoryzacją, ponieważ teraz „zablokowałeś” wszystkie istniejące zachowania.
Narzędzie Asis polega właśnie na utrzymywaniu starszego kodu poprzez automatyczne tworzenie i uruchamianie testów charakteryzacji.
Aby uzyskać więcej informacji, zobacz
Jedną z alternatyw dla testów jednostkowych, również wprowadzoną w sekcji Efektywna praca ze starszym kodem, są testy charakteryzacji . Z takimi testami miałem ciekawe wyniki. Są łatwiejsze do skonfigurowania niż testy jednostkowe podczas testowania z punktu, niż można je przetestować (zwane szwem). Wadą jest to, że gdy test się nie powiedzie, masz mniej wskazówek co do lokalizacji problemu, ponieważ testowany obszar może być znacznie większy niż w przypadku testów jednostkowych. Logowanie pomaga tutaj.
Struktury testów jednostkowych, takie jak te z rodziny xUnit, mogą być używane do pisania testów charakteryzacji.
W takich testach, pisanych po faktach, asercje weryfikują bieżące zachowanie kodu. W przeciwieństwie do testów jednostkowych nie udowadniają, że kod jest poprawny, po prostu określają (charakteryzują) bieżące zachowanie kodu.
Proces jest podobny jak w przypadku TDD:
Testy zakończą się niepowodzeniem, jeśli zmodyfikujesz zewnętrzne zachowanie kodu. Zewnętrzne zachowanie kodu? brzmi znajomo ? Tak jest, oto jesteśmy. Teraz możesz refaktoryzować kod.
Oczywiście ryzyko zależy od zakresu badań charakterystyk.
Zapoznaj się z bezpłatną biblioteką narzędzi do testów jednostkowych typu open source, ApprovalTests . Jeśli jesteś programistą .NET, twórca, Llewellyn Falco, nakręcił serię filmów pokazujących, w jaki sposób używa ApprovalTests do ulepszenia testów jednostkowych zarówno dla nowego, jak i starszego kodu.
Jeśli planujesz refaktoryzację starszego kodu, utworzenie tych testów jednostkowych jest koniecznością. Nie martw się o mockowanie lub stubbing - martw się o testowanie danych wejściowych i wyjściowych systemu, aby zmiany lub refaktoryzacja nie zakłócały bieżącej funkcjonalności.
Nie będę cię okłamywał, doposażenie testów jednostkowych do starszego kodu jest trudne - ale warto.
Już jakiś czas temu mówiłem o idei Reversed Tests Pyramid in Legacy Code na XPDays http://xpdays.com.ua/archive/xp-days-ukraine-2012/materials/legacy-code/
Ta prezentacja powinna odpowiedzieć na pytanie, dlaczego tak ważne jest czasami rozpoczęcie od testów integracyjnych / funkcjonalnych lub nawet testów akceptacyjnych wysokiego poziomu podczas pracy ze starszym kodem. A potem powoli, krok po kroku, wprowadzając testy jednostkowe. Nie ma przykładów kodu - przepraszam, ale kilka z nich można znaleźć w książce Michaels Feathers „Efektywna praca z Legacy Code”.
Możesz również sprawdzić Legacy Code Retreat http://www.jbrains.ca/legacy-code-retreat i poszukać tego spotkania w Twojej okolicy.