Zadanie polega na poddaniu starszej aplikacji testowi jednostkowemu. Najpierw podstawowe informacje o aplikacji: jest to baza kodów RCP Java LOC o wielkości 600 000 LOC z tymi głównymi problemami
- masowe powielanie kodu
- bez enkapsulacji, większość danych prywatnych jest dostępna z zewnątrz, niektóre dane biznesowe również stały się singletonami, więc można je zmieniać nie tylko z zewnątrz, ale także zewsząd.
- brak abstrakcji (np. brak modelu biznesowego, dane biznesowe są przechowywane w Object [] i podwójnie [] []), więc nie ma OO.
Istnieje dobry zestaw testów regresji, a sprawny zespół kontroli jakości testuje i znajduje błędy. Znam techniki sprawdzania tego z klasycznych książek, np. Michael Feathers, ale to jest zbyt wolne. Ponieważ istnieje działający system testów regresji, nie boję się agresywnego refaktoryzacji systemu, aby umożliwić pisanie testów jednostkowych.
Jak powinienem zacząć atakować problem, aby szybko uzyskać zasięg , aby móc pokazać postępy w zarządzaniu (i faktycznie zacząć zarabiać z siatki bezpieczeństwa testów JUnit)? Nie chcę używać narzędzi do generowania zestawów testów regresji, np. AgitarOne, ponieważ testy te nie sprawdzają, czy coś jest poprawne.
źródło
Odpowiedzi:
Uważam, że istnieją dwie główne osie, wzdłuż których można umieścić kod, jeśli chodzi o wprowadzenie testów jednostkowych: A) jak testowalny jest kod? i B) jak stabilny jest (tj. jak pilnie potrzebuje testów)? Patrząc tylko na skrajności, daje to 4 kategorie:
Kategoria 1 to oczywiste miejsce na start, w którym możesz uzyskać wiele korzyści przy stosunkowo niewielkiej pracy. Kategoria 2 pozwala szybko poprawić statystyki pokrycia (dobre dla morale) i uzyskać więcej doświadczenia z bazą kodu, podczas gdy kategoria 3 to więcej (często frustrujące) prace, ale także przynosi więcej korzyści. To, co powinieneś zrobić najpierw, zależy od tego, jak ważne są dla ciebie statystyki morale i zasięgu. Kategoria 4 prawdopodobnie nie jest warta zawracania sobie głowy.
źródło
Mam duże doświadczenie w pracy na starszych systemach (choć nie Java), znacznie większych niż to. Nienawidzę być nosicielem złych wiadomości, twój problem jest wielkości twojego problemu. Podejrzewam, że nie doceniłeś tego.
Dodanie testów regresji do starszego kodu jest powolnym, kosztownym procesem. Wiele wymagań nie jest dobrze udokumentowanych - tutaj naprawiono błąd, poprawkę, a zanim się zorientujesz, oprogramowanie określa własne zachowanie. Brak testów oznacza, że wystarczy przejść na wdrożenie, nie ma testów, które mogłyby „zakwestionować” ukryte wymagania zaimplementowane w kodzie.
Jeśli spróbujesz szybko uzyskać ochronę, prawdopodobnie spiesz się z pracą, upiecz ją na pół i zawiedzie. Testy zapewnią częściowe omówienie oczywistych rzeczy, a słabe - brak pokrycia prawdziwych problemów. Przekonasz tych menedżerów, których próbujesz sprzedać, że Testowanie Jednostkowe nie jest tego warte, że jest to kolejna srebrna kula, która nie działa.
IMHO, najlepszym podejściem jest skierowanie cię na testy. Skorzystaj z miar, raportów jelita i raportów błędów, aby zidentyfikować 1% lub 10% kodu, który powoduje najwięcej problemów. Uderz mocno w te moduły i zignoruj resztę. Nie próbuj robić zbyt wiele, mniej znaczy więcej.
Realistycznym celem jest „Od czasu wdrożenia UT, wstawianie defektów w testowanych modułach spadło do x% tych, które nie są pod UT” (idealnie x jest liczbą <100).
źródło
Przypomniało mi się to powiedzenie o tym, że nie martwię się o drzwi stodoły, kiedy koń już pędzi.
Rzeczywistość jest taka, że naprawdę nie ma opłacalnego sposobu na uzyskanie dobrego pokrycia testowego dla starszego systemu, z pewnością nie w krótkim czasie. Jak wspomniał MattNz, będzie to bardzo czasochłonny proces, a ostatecznie wyjątkowo kosztowny. Moja intuicja mówi mi, że jeśli spróbujesz zrobić coś, aby zrobić wrażenie na zarządzaniu, prawdopodobnie stworzysz nowy koszmar konserwacji, ponieważ próbujesz zbyt szybko pokazywać zbyt wiele, bez pełnego zrozumienia wymagań, które próbujesz przetestować.
Realistycznie, po napisaniu kodu, jest już prawie za późno, aby napisać testy skutecznie bez ryzyka pominięcia czegoś istotnego. Z drugiej strony można powiedzieć, że niektóre testy są lepsze niż brak testów, ale w takim przypadku same testy muszą wykazać, że wnoszą wartość dodaną do systemu jako całości.
Moją sugestią byłoby przyjrzenie się kluczowym obszarom, w których czujesz, że coś jest „zepsute”. Rozumiem przez to, że może to być bardzo nieefektywny kod lub że można wykazać, że jego utrzymanie było wcześniej kosztowne. Udokumentuj problemy, a następnie wykorzystaj to jako punkt wyjścia do wprowadzenia poziomu testowania, który pomoże Ci ulepszyć system, bez podejmowania ogromnych wysiłków związanych z przeprojektowaniem. Chodzi tutaj o to, aby uniknąć nadrabiania zaległości w testach, a zamiast tego wprowadzić testy, które pomogą Ci rozwiązać określone problemy. Po pewnym czasie sprawdź, czy możesz zmierzyć i rozróżnić poprzedni koszt utrzymania tej sekcji kodu oraz bieżące wysiłki związane z poprawkami, które zastosowałeś w ich testach pomocniczych.
Należy pamiętać, że kierownictwo jest bardziej zainteresowane kosztem / korzyściami i tym, jak bezpośrednio wpływa to na ich klientów, a ostatecznie na ich budżet. Nigdy nie są zainteresowani robieniem czegoś po prostu dlatego, że jest to najlepsza rzecz, chyba że możesz udowodnić, że zapewni im to interesującą ich korzyść. Jeśli jesteś w stanie wykazać, że poprawiasz system i otrzymujesz dobre pokrycie testowe dla pracy, którą obecnie wykonujesz, kierownictwo jest bardziej skłonne postrzegać to jako skuteczne zastosowanie twoich wysiłków. Może to pozwolić ci na argumentowanie za rozszerzeniem swoich wysiłków na inne kluczowe obszary, bez wymagania albo całkowitego wstrzymania rozwoju produktu, albo, co gorsza, prawie niemożliwego do argumentowania za przepisaniem!
źródło
Jednym ze sposobów na poprawę zasięgu jest napisanie większej liczby testów.
Innym sposobem jest zmniejszenie nadmiarowości w kodzie, tak aby istniejące testy faktycznie obejmowały nadmiarowy kod, który nie jest obecnie objęty.
Wyobraź sobie, że masz 3 bloki kodu, a, b i b ', gdzie b' to duplikat (dokładna lub prawie brakująca kopia) B i że masz zasięg na aib, ale nie b 'z testem T.
Jeśli zmienimy podstawę kodu, aby wyeliminować b ', wyodrębniając podobieństwo zb i b' jako B, podstawa kodu wygląda teraz jak a, b0, B, b'0, przy czym b0 zawiera nieudostępniony kod z b'0 i odwrotnie versa, a zarówno b0, jak i b'0 są znacznie mniejsze niż B i wywoływanie / używanie B.
Teraz funkcjonalność programu się nie zmieniła, podobnie jak test T, więc możemy uruchomić T ponownie i oczekiwać, że przejdzie. Kod objęty teraz to a, b0 i B, ale nie b'0. Baza kodu stała się mniejsza (b'0 jest mniejsza niż b '!) I nadal pokrywamy to, co pierwotnie pokryliśmy. Nasz wskaźnik zasięgu wzrósł.
Aby to zrobić, musisz znaleźć b, b 'i idealnie B, aby umożliwić refaktoryzację. Nasz CloneDR narzędzie może to zrobić w wielu językach, zwłaszcza w Javie. Mówisz, że twoja baza kodu ma dużo zduplikowanego kodu; może to być dobry sposób na rozwiązanie tego z korzyścią.
Co dziwne, czynność znajdowania b i b 'często poszerza Twoje słownictwo na temat abstrakcyjnych pomysłów realizowanych przez program. Chociaż narzędzie nie ma pojęcia, co robią b i b ', sam fakt odizolowania ich od kodu, umożliwiając proste skupienie się na treści b i b', często daje programistom bardzo dobre wyobrażenie o tym, jaką abstrakcję B_abstract implementuje sklonowany kod . To poprawia zrozumienie kodu. Upewnij się, że nadasz B dobre imię, gdy go odrzucisz, a dostaniesz lepszy zasięg testu i łatwiejszy w utrzymaniu program.
źródło