Pracuję nad rozwojem starego projektu napisanego w Javie. Mamy ponad 10 milionów LOC, a co gorsza, ponad 4000 testów funkcjonalnych.
Testy zaplanowane przez Hudsona zawodzą jak szalone przy każdej większej zmianie kodu. Weryfikacja niepowodzenia testu - jeśli jest to problem w produkcie lub w teście, zajmuje miesiące. Nie możemy usunąć starych testów, ponieważ nie wiemy, co testują!
Co możemy zrobić? Jak przejść z taką ilością starszych testów?
integration-tests
legacy-code
jenkins
Hector Brosuli
źródło
źródło
Odpowiedzi:
Porzuć ich.
Wiem, że ciężko jest puścić coś, co wyraźnie wymagało wysiłku, ale testy nie działają dla ciebie, działają przeciwko tobie. Zestaw testowy powinien dać ci pewność, że system robi to, co powinien. Jeśli tak się nie stanie, jest to zobowiązanie zamiast aktywów. Nie ma znaczenia, czy system lub testy są winne - dopóki uruchomienie zestawu testów sygnalizuje ogromne ilości błędów, nie może spełnić swojego celu.
Teraz potrzebujesz nowego zestawu testów, który działa bez błędów. Oznacza to, że początkowo będzie miał niewielki zasięg, w rzeczywistości prawie żaden zasięg. Za każdym razem, gdy naprawiasz lub poświęcasz czas na dokładne zrozumienie czegoś na temat swojego systemu, zmieniasz tę wiedzę w teście. Z czasem stworzy to nową siatkę bezpieczeństwa, na której możesz budować w przyszłości. Próba załatania starej, niezrozumiałej siatki bezpieczeństwa jest pochłaniaczem czasu, który prawie nigdy nie jest opłacalny.
Odradzałbym nawet przenoszenie testów ze starego pakietu do nowego. Pewnie, niektórzy z nich mogą teraz odnieść sukces, ale czy to dlatego, że testują dokładnie to, co powinni przetestować, czy tylko dlatego, że niektóre losowe strzały zawsze trafiają w cel? Oczywiście musisz być pragmatyczny w kwestii tego, co można, a czego nie można zrobić, wysiłkiem, jaki możesz wydać, ale nie możesz iść na kompromis w sprawie zasady, że zestaw testów musi działać poprawnie, aby wykonać swoją pracę .
źródło
Idź i napraw testy.
Twoim największym błędem jest to, że pozwoliłeś, by testy zakończyły się niepowodzeniem, i oczywiście zignorowałeś to przez pewien czas. To, co masz, to nie „starsze testy” - pracujesz nad starszym kodem. I uważam, że każdy kod napisany bez testów jest dziedzictwem.
Wygląda na to, że w Twojej organizacji jest jeszcze większy problem, ponieważ nie pracujesz z jasnymi wymaganiami. Nie rozumiem, że ty (lub ktoś inny) nie możesz potwierdzić właściwego zachowania.
źródło
Testy są cenne. Przynajmniej nagrywają, że ktoś uważał, że powinien poświęcić czas na ich pisanie, więc prawdopodobnie mieli kiedyś dla kogoś jakąś wartość. Przy odrobinie szczęścia będą one zawierać kompletny zapis wszystkich funkcji i błędów, nad którymi zespół kiedykolwiek pracował - chociaż mogą być również sposobem na zdobycie dowolnego numeru zasięgu testu bez dokładnego przemyślenia. Dopóki na nie nie spojrzysz, nie będziesz wiedział, co jest prawdą tutaj.
Jeśli większość testów mija większość czasu, po prostu ugryź pocisk i zainwestuj czas w ustalenie, co próbowało zrobić kilka testów, które nie powiodły się, oraz poprawienie lub ulepszenie, aby zadanie było łatwiejsze następnym razem. W takim przypadku przejdź do sekcji Określenie intencji każdej sekcji testowej , aby uzyskać porady dotyczące postępowania z niewielką liczbą nieudanych testów.
Z drugiej strony możesz mieć teraz do czynienia z czerwoną wersją i setkami, a nawet tysiącami testów, które od dawna nie przeszły, a Jenkins od dawna nie był zielony. W tym momencie status kompilacji Jenkins stał się bezużyteczny, a kluczowy wskaźnik problemów z odprawą nie działa. Musisz to naprawić, ale nie możesz sobie pozwolić na zatrzymanie wszystkich postępów podczas sprzątania bałaganu w salonie.
Aby zachować zdrowie psychiczne podczas wykonywania wymaganej archeologii w celu ustalenia, jaką wartość można odzyskać po nieudanych testach, zalecam następujące kroki:
Tymczasowo wyłącz nieudane testy.
Istnieje kilka sposobów, w jaki możesz to zrobić, w zależności od środowiska, których nie opisujesz wyraźnie, więc nie mogę polecić żadnego z nich.
Niektóre platformy obsługują pojęcie oczekiwanych awarii. Jeśli tak, to świetnie, bo zobaczysz odliczanie, ile testów pozostało w tej kategorii, a nawet zostaniesz poinformowany, jeśli niektóre z nich zaczną nieoczekiwanie przejść.
Niektóre frameworki obsługują grupy testowe i pozwalają Hudsonowi na uruchomienie tylko niektórych testów lub pominięcie grupy testów. Oznacza to, że możesz czasami uruchomić grupę testową ręcznie, aby sprawdzić, czy któraś z nich teraz przechodzi.
Niektóre frameworki umożliwiają dodawanie adnotacji lub w inny sposób oznaczanie pojedynczych testów do zignorowania. W tym przypadku trudniej jest prowadzić ich jako grupę, ale powstrzymuje ich to przed rozpraszaniem.
Możesz przenieść testy do drzewa źródłowego, które zwykle nie jest zawarte w kompilacji.
W ekstremalnych przypadkach możesz usunąć kod z HEAD systemu kontroli wersji, ale utrudni to rozpoznanie po zakończeniu trzeciej fazy.
Celem jest sprawienie, aby Jenkins poszedł na zielono tak szybko, jak to możliwe, abyś mógł jak najszybciej zacząć podążać we właściwym kierunku.
Utrzymuj odpowiednie testy.
Postanowić dodać nowe testy podczas dodawania lub modyfikacji kodu i zobowiązać się do zachowania pozytywnego wyniku wszystkich testów.
Testy mogą się nie powieść z różnych powodów, w tym z faktu, że nie były to dobrze napisane testy na początek. Ale kiedy już staniesz się zielony Jenkins, utrzymanie go w ten sposób jest naprawdę ważne.
Przyzwyczaj się do pisania dobrych testów i spraw, aby było to bardzo ważne, jeśli testy zaczną się nie powieść.
Określ cel każdego testu.
Przejrzyj kolejno wyłączone testy. Zacznij od tych, które wpływają na najczęściej zmieniane moduły. Określ cel testu i przyczynę niepowodzenia.
Czy celowo testuje funkcję, która została specjalnie usunięta z kodu? Następnie prawdopodobnie możesz go usunąć.
Czy łapie błąd, którego nikt jeszcze nie zauważył? Przywróć test i napraw błąd.
Czy to się nie udaje, ponieważ przyjmował nieuzasadnione założenia (np. Zakładając, że tekst przycisku będzie zawsze w języku angielskim, ale teraz zlokalizowałeś aplikację na wiele języków)? Następnie dowiedz się, w jaki sposób skoncentrować test na jednej rzeczy i jak najlepiej oddzielić go od niezwiązanych zmian.
Czy test rozciąga się na całą aplikację i reprezentuje test systemu? Następnie usuń go z głównego zestawu testów Jenkins i dodaj do zestawu regresji, który działa rzadziej.
Czy architektura aplikacji zmieniła się nie do poznania, więc test już nic nie przydaje? Usuń to.
Czy test został dodany, aby sztucznie zwiększyć statystyki pokrycia kodu, ale w rzeczywistości nic poza potwierdzeniem, że kod poprawnie się kompiluje i nie przechodzi w nieskończoną pętlę? A może test po prostu potwierdza, że wybrana frakcja próbna zwraca wyniki, o których właśnie jej powiedziałeś? Usuń to.
W wyniku tego niektóre testy się utrzymają, niektóre zostaną zmodyfikowane, niektóre podzielone na wiele niezależnych fragmentów wielkości kęsa, a niektóre usunięte. Tak długo, jak nadal robisz postępy w zakresie nowych wymagań, musisz poświęcić trochę czasu na poradzenie sobie z technicznym zadłużeniem w ten sposób.
źródło
4000 testów to trudny do rozwiązania problem. 40 testów jest łatwiejszych w obsłudze. Losowo wybierz zarządzalną liczbę testów do uruchomienia i analizy. Sklasyfikuj wyniki jako:
Jeśli wiele testów zalicza się do pierwszej kategorii, być może nadszedł czas, aby wyrzucić bieżący zestaw testów i przygotować użyteczny dla bieżącego kodu.
Jeśli wiele testów kończy się niepowodzeniem w sposób informujący o problemie w kodzie, musisz przejść przez testy zakończone niepowodzeniem, które naprawiają problemy. Może się okazać, że usunięcie jednego lub dwóch błędów powoduje uruchomienie dużej liczby testów.
źródło
Jeśli to stwierdzenie jest prawdziwe,
oznacza to, że jeśli cofniesz się do kodu tuż przed „większą zmianą kodu”, wówczas wiele testów przejdzie ponownie. Po zrobieniu tego, weź mniejszy kawałek zmian i zobacz, które testy zakończyły się niepowodzeniem. Pomoże to lepiej określić, które zmiany kodu powodują niepowodzenia testów. W przypadku każdego testu po usunięciu problemu powinieneś być w stanie ustalić, czy nowy kod był wadliwy, czy test był. Jeśli jest to problem z nowym kodem, koniecznie porównaj go z najnowszą wersją na wypadek, gdyby dany błąd został już naprawiony.
Powtarzaj, aż będziesz mieć najnowszą bazę kodu.
Może się to wydawać przytłaczającym zadaniem, ale bardzo prawdopodobne jest, że kiedy przejdziesz tą ścieżką i zaczniesz izolować niektóre problemy, zacznie się pojawiać wzór, który może znacznie przyspieszyć proces. Na przykład:
źródło
Jeśli nie wiesz, co testują, usuń je, dopóki się nie dowiesz. Testy są płynne, jeśli usuniesz funkcję, która nie jest już wymagana, powinieneś spodziewać się zmiany testu testującego tę funkcję! Więc jeśli nie wiesz, co testują testy, nie masz nadziei na zmianę bazy kodu z nimi na miejscu.
Możesz skonfigurować system testowy na komputerach programistów i uruchomić go, aby deweloperzy mogli zobaczyć, z jakimi częściami testują interakcje, mam nadzieję, że dostarczą tę brakującą dokumentację i lepiej zapoznają się z bazą kodu, której nie zmieniasz poprawnie, lub nie dłuższe testowanie poprawnie.
W skrócie - jeśli twoje stare testy kończą się niepowodzeniem podczas wprowadzania zmian, zmiany w kodzie nie są dobre. Użyj tych testów jako środka edukacyjnego w zakresie działania systemu.
źródło
@Ignore
adnotacja JUnit - możesz zachować swoje testy, ale ich nie wykonywać. Następnie wystarczy po prostu włączyć je ponownie i naprawić pojedynczo. Pozwala zawęzić koncentrację na zaledwie kilku testach na raz, zamiast być przytłoczonym tysiącami awarii.Najważniejszą rzeczą, jaką bym zrobił, to powrót do podstaw tego, co powinno robić testowanie i czego potrzebuje firma, aby móc się poruszać. Zadaniem testowania jest identyfikacja problemów, zanim będą kosztowne do rozwiązania w późniejszym terminie. Myślę, że kluczowym słowem w tym zdaniu jest „drogi”. Te problemy wymagają rozwiązania biznesowego. Czy w terenie pojawiają się kosztowne problemy? Jeśli tak, testowanie kończy się niepowodzeniem.
Twoje kierownictwo i musisz przejść kontrolę rzeczywistości. Przekonasz się, że koszty rozwoju gwałtownie rosną z powodu starszego zestawu testów. Jak te koszty porównują się do kosztów dostarczenia wadliwego produktu, ponieważ wyłączyłeś testy? Jak porównują się do uciążliwego zadania polegającego na ustaleniu, jakich zachowań potrzebują użytkownicy (jakie rzeczy należy przetestować)?
Są to problemy wymagające rozwiązań biznesowych, ponieważ dotykają biznesowej strony pracy. Dostarczasz produkt do klienta i jest to granica, która jest bardzo zainteresowana biznesem. Może on być w stanie zidentyfikować rozwiązania, których Ty, jako programista, nie możesz. Na przykład rozsądne może być dostarczenie dwóch produktów: jednego „starszego” produktu dla tych, którzy potrzebują niezawodności i chcą zrezygnować z nowych funkcji, z jednym „wizjonerskim” produktem, który może mieć więcej wad, ale jest pionierem. Dałoby to ci możliwość opracowania dwóch niezależnych zestawów testów ... jednego starszego z 4000 testów i jednego z większą liczbą testów, które według ciebie należy wykonać (i udokumentować je, aby proces się nie powtarzał).
Następnie zaczyna się sztuka: jak poradzić sobie z tą dwugłową bestią, aby postępy w jednej gałęzi pomagały drugiej gałęzi? W jaki sposób Twoje aktualizacje oddziału „Visonary” mogą wrócić do gałęzi „Legacy”, pomimo rygorystycznych wymagań testowych. W jaki sposób ciągłe żądania klientów w oddziale „starszej generacji” mogą lepiej kształtować twoje zrozumienie wymagań, których potrzebowaliby Twoi dotychczasowi klienci, gdybyś ostatecznie ponownie połączył produkty?
źródło
Właśnie dlatego powinieneś usunąć stare testy! Jeśli nie wiesz, co robią, to porażka jest bez znaczenia, a ich uruchomienie to strata czasu. Wyrzuć je i zacznij od nowa.
źródło