Jak radzić sobie z ogromną liczbą nieudanych testów? [Zamknięte]


22

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?


6
Prawdziwe pytania mają odpowiedzi. Zamiast wyjaśniać, dlaczego twoja sytuacja jest okropna lub dlaczego twój szef / współpracownik sprawia, że ​​jesteś nieszczęśliwy, wyjaśnij, co chcesz zrobić, aby to poprawić. Aby uzyskać więcej informacji, kliknij tutaj ...
gnat

13
Dlaczego pozwoliłeś, by testy zaczęły się nie powieść? BTW 4000 to nie tyle testów na 10 MLOC
BOCовић

6
Zatrzymaj, upuść i rzuć.
Navin

13
Dowiedz się, co testują testy. Następnie ponownie przejrzyj i zastanawiaj się przede wszystkim, jak na ziemi testy trwają miesiące, aby znaleźć problem, a także dowiedzieć się, jak bardzo zmieniły się Twoje wymagania. Testy mają na celu zamknięcie wymagań w aplikacji. Jeśli testy zakończą się niepowodzeniem, kod nie działa zgodnie z wymaganiami - albo napisałeś je niepoprawnie, albo żaden kod nie spełnia Twoich wymagań.
Dan Pantry

6
Wszyscy widzieliśmy, jak kompilator wyrzuca zylion błędów z powodu pojedynczego brakującego „}”. Jeśli są to testy funkcjonalne z mnóstwem zależności, być może działa ten sam problem?
Dan Pichelman

Odpowiedzi:


37

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ę .


9
Nie rozumiem logiki w twoim punkcie: „Zestaw testowy powinien dać ci pewność, że system robi to, co powinien. [...] Teraz potrzebujesz nowego zestawu testów, który działa bez błędy ”. Jeśli masz wadliwy kod, który powoduje, że testy kończą się niepowodzeniem, nie oznacza to, że powinieneś ponownie napisać testy, aby przekazać błędny kod.
DBedrenko,

13
Sytuacja Hektora polega na tym, że nie wie on, czy kod lub testy są nieprawidłowe . Gdyby to zrobił, mógłby pracować z bazą kodu i czasami zmieniać testy, czasem kod biznesowy. W rzeczywistości nawet tego rodzaju prace nie byłyby opłacalne, ponieważ nie wiesz, czy naprawiasz problemy, czy je perpetujesz.
Kilian Foth,

5
„Zestaw testowy powinien dać ci pewność, że system robi to, co [powinien].” Nie, ma mi powiedzieć, czy system robi to, co powinien; fałszywe zaufanie jest gorsze niż żadne. „Potrzebny jest zestaw testowy, który działa bez błędów” Nie, to, czego potrzebuje, to zestaw testowy, który daje mu użyteczne informacje na temat poprawności kodu. Teraz ma wiele tajemniczych świateł ostrzegawczych, które są lepsze niż zielone światło z błyszczącego nowego zestawu testów, który niczego nie testuje. Powinien tymczasowo wyłączyć stare testy , ale nie rezygnować z tych, których nie zweryfikował jako fałszywych.
Beta

4
Ta odpowiedź to niesamowicie zła rada! Jeśli mniejsze zmiany kodu prowadzą do dużej liczby nieudanych testów, prawdopodobnie występują problemy z jakością kodu. Test przynajmniej poinformuje cię, że coś złamałeś. Musisz poprawić kod (poprzez staranne refaktoryzowanie wspomagane testami). Jeśli po prostu usuniesz testy, nie będziesz mógł wiedzieć, czy coś zepsułeś.
JacquesB

4
To okropna rada. Jeśli OP i jego zespół już nie rozumieją bazy kodu i jego testów, przerzucenie testów i rozpoczęcie od nowa raczej nie rozwiąże podstawowego problemu OP - zrozumienia bazy kodu. Myślę, że możemy założyć, że testy zadziałały, gdy zostały napisane - więc jego zespół musi wyśledzić, co testuje każdy test, i przeczytać źródło, aby ustalić, czy jest to podstawa kodu, czy test, który jest dzisiaj zły. O wiele prostsze niż rozpoczęcie od błędnie przeprowadzonych i nie poinformowanych / naiwnych testów.
SnakeDoc,

29

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.


Weryfikacja niepowodzenia testu - jeśli występuje problem z produktem lub testem, zajmuje miesiące. Nie możemy usunąć starych testów, ponieważ nie wiedzieliśmy, co testują!

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.


4
Idealnie powinno się to zrobić, ale wydaje się, że testy tutaj są tak złe, że programiści nawet nie wiedzą, co testują. Myślę, że w tym przypadku najlepiej jest pozbyć się testów WTF i od razu zacząć pisać nowe, znaczące! W ostatnim projekcie miałem podobny problem ze współpracownikiem, którego testy zawsze kończyły się niepowodzeniem bez ważnych powodów (nie zawiodło, ponieważ to, co miało być testowane, poszło nie tak, ale ponieważ kod testu był tak kruchy, a nawet deterministyczny!) . Spędziłem dni przepisując, co mogłem, a resztę zniszczyłem!
Shautieh

@Shautieh Testy WTF nie przebiegają bez kodu WTF, więc testy naprawcze zwykle oznaczają refaktoryzację kodu. A losowo nieudane testy są oznaką niekompetencji. A przełożony twojej koleżanki jest winny za to, że nie wykonali swojej pracy.
BЈовић

2
Czasami życie jest trudne: facet odpowiedzialny za testy WTF (i kod) zdobył najwyższe wynagrodzenie w zespole (20 +% więcej niż ja), a kiedy zrezygnował w połowie projektu (ponieważ znalazł lepiej płatną pracę ) Musiałem podjąć się kilku jego twórców: / Ale masz całkowitą rację, twierdząc, że nasz przełożony też był winny ^^
Shautieh

@Shautieh: mój kolega powiedział kiedyś, że błąd w kodzie to dwa błędy: błąd w kodzie i martwy punkt w testach. Sądzę, że to właściwie trzy, jeśli liczyć dewelopera, który toleruje nieudane testy, i cztery, jeśli liczyć menedżerów, którzy promują takie niekompetencje.
Beta

@Beta Brzmi dość podobnie do definicji czasem używanej w TDD: „Błąd to test, którego jeszcze nie napisałeś”.
Przywróć Monikę

22

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.


1
Wyłączenie testów tylko dlatego, że się nie powiedzie, jest naprawdę bardzo złym pomysłem! Reszta twoich rad jest dobra, ale nie to. Testy, których nie rozumiesz, nigdy nie powinny być wyłączone. Celem testowania nie jest uzyskanie zielonego paska, chodzi o uzyskanie działającego oprogramowania!
JacquesB

To zależy od skali problemu. Ale zgadzam się, że tak naprawdę nie wyjaśniłem tego.
Bill Michell

Dodano akapit rozróżniający między „jesteśmy zieleni, ale każda zmiana powoduje, że rzeczy stają się czerwone” i „byliśmy tak czerwoni, że zapomnieliśmy, jak wygląda zieleń”
Bill Michell

Zamiast wyłączać lub nawet usuwać test, niektóre frameworki zapewniają także pojęcie oczekiwanej awarii . Może to pomóc zwiększyć SNR, ponieważ będziesz bardziej bezpośrednio powiadamiany o nowych awariach (czego nie zrobisz, jeśli zawsze istnieje ogromna liczba awarii), ale nadal będziesz powiadamiany o znanych awariach i - być może nawet ważniejsze - gdy poprzednio nieudany test nagle przechodzi ponownie. Jeśli nieoczekiwane awarie zostaną odczytane, a spodziewane awarie pomarańczowe, spraw, aby czerwone testy były zielone jako pierwsze, a pomarańczowe - drugie.
5gon12eder

11

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:

  1. Bezużyteczny test
  2. Przydatny test, który działa czysto
  3. Przydatny test, który się nie udaje

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.


2
+ (int) (PI / 3) za zapewnienie rzeczywistego i prostego sposobu testowania zestawu testów - podczas gdy zgadzam się, że z reguły testy takie jak opisane przez OP są oznaką wadliwego projektu - ale bez testowania co jest nie tak, każda rada dotycząca samego zestawu testów (czy to „porzuć je”, „napraw testy”, „napisz nowe testy”) jest po prostu bezużyteczna. Dokładnie tak, jak mówisz: gdybym miał testy 4k, a dla 40 całkowicie losowych z tych 3/4 byłyby kiepskie i bezużyteczne - nie wahałbym się rzucić całego pakietu. Jeśli 3/4 z nich byłoby naprawdę przydatne - zostawiłbym je i skupiłem się na ulepszeniu kodu.
vaxquis

7

Jeśli to stwierdzenie jest prawdziwe,

Testy ... zawodzą jak szalone przy każdej większej zmianie kodu.

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:

  • Możesz zauważyć, że wiele testów zależy od czegoś innego, co jest wadliwe. Naprawienie tego jednego elementu może naprawić wiele testów.
  • Możesz zauważyć, że wiele testów jest wadliwych i trzeba je naprawić lub usunąć.
  • Możesz zauważyć, że konkretny programista ma znacznie większą częstotliwość powodowania przerwania testów. Ten programista może potrzebować więcej szkoleń lub nadzoru.

3

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.


1
Dlatego podoba mi się @Ignoreadnotacja 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.
TMN

1
To zła rada. Nie należy usuwać ani wyłączać testu, którego nie rozumiesz. Tylko jeśli zrobić zrozumieć test, i jesteśmy pewni, że testuje przestarzałego funkcję, powinny być zablokowane lub usunięte.
JacquesB

2

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?


-3

Nie możemy usunąć starych testów, ponieważ nie wiedzieliśmy, co testują!

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.


2
wydaje się, że jest to tylko powtórzenie punktu, który został już wyjaśniony i wyjaśniony w najwyższej odpowiedzi
gnat

4
Awaria nie jest „bez znaczenia”, oznacza to, że nie rozumiesz systemu tak dobrze, jak myślałeś.
Ben Voigt,

Niepowodzenie jest tutaj zdecydowanie bez znaczenia, ponieważ PO wyraźnie stwierdził, że nie rozumie systemu.
Mohair
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.