Jaki jest uzasadniony% pokrycia kodu dla testów jednostkowych (i dlaczego)? [Zamknięte]


604

Jeśli miałbyś wprowadzić minimalny procent pokrycia kodu dla testów jednostkowych, być może nawet jako wymóg zatwierdzenia repozytorium, co by to było?

Proszę wyjaśnić, w jaki sposób dotarliście do swojej odpowiedzi (ponieważ jeśli wszystko, co zrobiliście, to wybraliście numer, to mógłbym to zrobić sam;)


Teraz wiele dni IDE ma podświetlanie pokrycia, upewnij się, że obejmujesz najważniejsze części kodu przynajmniej niż myślenie o osiągnięciu określonego procentu.
Wszystkie od

4
Symbol% ​​to zapach kodu dla metryk (również% to ogólnie bzdura)
Hernán Eche

Testy jednostkowe z definicji mogą być pojedynczymi metodami, całymi klasami lub całymi modułami. Nawet jeśli przetestujesz wszystkie metody, możesz nie przetestować wszystkich ścieżek lub wszystkich kombinacji, które trafi użytkownik. Sytuacja staje się bardziej złożona w przypadku oświadczenia, zasięgu oddziałów i MCDC.
Ska

Dlaczego to pytanie nie jest usuwane ani poprawnie edytowane. Zebrał tak wiele zainteresowania, ale jest całkowicie mylący.
Ska

Odpowiedzi:


1390

Ta proza ​​Alberto Savoia odpowiada dokładnie na to pytanie (w tym całkiem przyjemnie!):

http://www.artima.com/forums/flat.jsp?forum=106&thread=204677

Testivus o pokryciu testowym

Pewnego ranka programista zapytał wielkiego mistrza:

„Jestem gotowy napisać kilka testów jednostkowych. W jakim zakresie kodu powinienem dążyć? ”

Wielki mistrz odpowiedział:

„Nie martw się zasięgiem, po prostu napisz kilka dobrych testów”.

Programista uśmiechnął się, ukłonił i wyszedł.

...

Później tego samego dnia drugi programista zadał to samo pytanie.

Wielki mistrz wskazał na garnek z wrzącą wodą i powiedział:

„Ile ziaren ryżu powinienem włożyć do tego garnka?”

Zaskoczony programista odpowiedział:

„Jak mogę ci powiedzieć? To zależy od tego, ile osób musisz karmić, jak bardzo są głodni, jakie inne jedzenie podajesz, ile masz ryżu i tak dalej. ”

„Dokładnie” - powiedział wielki mistrz.

Drugi programista uśmiechnął się, ukłonił i wyszedł.

...

Pod koniec dnia przyszedł trzeci programista i zadał to samo pytanie dotyczące pokrycia kodu.

„Osiemdziesiąt procent i nie mniej!” Odpowiedział mistrz surowym głosem, waląc pięścią w stół.

Trzeci programista uśmiechnął się, ukłonił i wyszedł.

...

Po tej ostatniej odpowiedzi młody uczeń podszedł do wielkiego mistrza:

„Świetny mistrzu, dziś słyszałem, że odpowiadasz na to samo pytanie dotyczące pokrycia kodu trzema różnymi odpowiedziami. Dlaczego?"

Wielki mistrz wstał z krzesła:

„Chodź ze mną na świeżą herbatę i porozmawiajmy o tym”.

Po napełnieniu filiżanek gorącą zieloną herbatą wielki mistrz zaczął odpowiadać:

„Pierwszy programista jest nowy i dopiero zaczyna testowanie. W tej chwili ma dużo kodu i żadnych testów. Przed nim jeszcze długa droga; skupienie się teraz na pokryciu kodu byłoby przygnębiające i zupełnie bezużyteczne. Lepiej, żeby przyzwyczaił się do pisania i przeprowadzania testów. Później może się martwić o zasięg. ”

„Z drugiej strony drugi programista ma duże doświadczenie zarówno w programowaniu, jak i testowaniu. Kiedy odpowiedziałem, pytając ją, ile ziaren ryżu powinienem umieścić w garnku, pomogłem jej zrozumieć, że ilość niezbędnych testów zależy od wielu czynników, a ona zna te czynniki lepiej niż ja - w końcu to jej kod . Nie ma jednej, prostej odpowiedzi, a ona jest wystarczająco mądra, aby poradzić sobie z prawdą i pracować z tym. ”

„Rozumiem - powiedział młody uczeń - ale jeśli nie ma jednej prostej odpowiedzi, to dlaczego odpowiedziałeś trzeciemu programistowi„ Osiemdziesiąt procent i nie mniej ”?

Wielki mistrz zaśmiał się tak głośno i głośno, że jego brzuch, dowód, że pił więcej niż tylko zieloną herbatę, opadał w górę iw dół.

„Trzeci programista chce tylko prostych odpowiedzi - nawet jeśli nie ma prostych odpowiedzi… a potem i tak ich nie stosuje”.

Młody uczeń i siwy wielki mistrz skończyli pić herbatę w kontemplacyjnej ciszy.


62
Brzmi jak argument przeciwko ogólnej koncepcji pokrycia kodu, jako metryka oceny przydatności testów jednostkowych. Jestem pewien, że wszyscy zgadzają się, że nie jest to idealny wskaźnik, ale mam nadzieję, że osobiste doświadczenie powinno wykazać pewną korelację między% CC a skutecznością testu jednostkowego ...
rozsądek

16
rozsądek - twoje zdanie jest dokładnie odzwierciedlone w odpowiedzi na „drugiego programistę”. Doświadczenie osobiste powinno to dyktować.
Jon Limjap

167
Idealna odpowiedź. Dane nie tworzą dobrego kodu. Możesz pisać kiepski kod ze 100% pokryciem i to nie poprawia działania kodu. +1 ode mnie, szkoda, że ​​nie mogę więcej :)
Rob Cooper

15
4 lata później i nadal przydatne. Właśnie wyciągnąłem to na dwóch moich kolegów dziś rano.
SickHippie

9
Dla mnie ta anegdota reprezentuje idealistyczny pogląd. W prawdziwym świecie zespołów projektowych o konkurencyjnych priorytetach pokrycie kodu wynosi 0%. Potrzebujemy wymaganej liczby, aby zbudować nawyk testowania jednostkowego w zespole. Przyszedłem do tego pytania, szukając wskazówek, jak ustalić ten numer dla obszaru, który nie jest mi zbyt dobrze zaznajomiony, i to naprawdę nie jest wcale pomocne. Cieszę się, że ludzie w innych scenariuszach uważają to za przydatne.
samspot,

85

Pokrycie kodu jest mylącym wskaźnikiem, jeśli Twoim celem jest pokrycie 100% (zamiast 100% testowania wszystkich funkcji).

  • Możesz uzyskać 100%, naciskając raz wszystkie linie. Jednak nadal możesz przeoczyć testowanie określonej sekwencji (ścieżki logicznej), w której trafiają te linie.
  • Nie można uzyskać 100%, ale nadal przetestowano wszystkie używane ścieżki kodu 80% / freq. Posiadanie testów, które sprawdzają każdy „wyjątek typu ExceptionTypeX” lub podobny defensywny programator, którego używasz, to „miło mieć”, a nie „trzeba mieć”

Zaufaj więc sobie lub swoim programistom, aby zachowali się rzetelnie i obejmowali każdą ścieżkę poprzez swój kod. Bądź pragmatyczny i nie ścigaj magicznego 100% zasięgu. Jeśli zgłaszasz kod TDD, powinieneś otrzymać 90% pokrycia jako bonus. Użyj pokrycia kodu, aby podświetlić fragmenty kodu, które zostały pominięte (nie powinno się to zdarzyć, jeśli TDD, chociaż ... ponieważ piszesz kod tylko w celu przejścia testu. Żaden kod nie może istnieć bez testu partnera)


4
- Wyjątki - jeśli nie przetestujesz obsługi wyjątków, skąd wiesz, że Twój kod się nie wysadza, kiedy to się dzieje? - Setters / Getters - chyba kontekstowe, ale z pewnością twoje testy powinny je wykonać jako część zestawu testów, a jeśli tak nie jest, to czy są faktycznie używane?
tddmonkey

1
Wyjątki powinny być wyjątkowe - nie powinny się zdarzyć. Jeśli tak, rejestrujesz punkt awarii i kaucję. Nie można przetestować każdego wyjątku, który może się zdarzyć. Jeśli aplikacja ma obsługiwać niezadowoloną ścieżkę / zdarzenie, powinieneś ją przetestować. Akcesoria mogą zostać dodane dla przyszłych klientów. Zależy
Gishu

5
Nie jestem pewien, co rozumiesz przez swój drugi punkt „ale nadal testowałem wszystkie ścieżki kodu”. Jeśli w rzeczywistości masz na myśli pełne pokrycie, to nie możesz mieć pełnego zasięgu bez 100% zasięgu linii / oddziału / decyzji. W rzeczywistości pokrycie pełnej ścieżki jest zwykle nieosiągalne w żadnym nietrywialnym programie ze względu na kombinatoryczny charakter gałęzi w generowaniu ścieżek. en.wikipedia.org/wiki/Code_coverage#Other_coverage_criteria
Zach Burlingame

3
Nie testujesz każdego możliwego wyjątku; oczywiście, że nie możesz tego zrobić. MUSISZ mierzyć testowanie każdego bloku kodu, który obsługuje wyjątki. Na przykład, jeśli istnieje wymóg, że gdy blok X zgłasza wyjątek, wyjątek jest rejestrowany w bazie danych, zielony pasek u dołu ekranu zmienia kolor na czerwony, a papież otrzymuje wiadomość e-mail; to powinieneś przetestować. Ale nie musisz testować każdego możliwego wyjątku, który może wywołać te zdarzenia.
Dawood ibn Kareem

2
+1 dla „Użyj pokrycia kodu, aby podświetlić fragmenty kodu, które zostały pominięte”. Właśnie do tego służy ta metryka.
beluchin

61

Zasięg kodu jest świetny, ale zasięg funkcjonalności jest jeszcze lepszy. Nie wierzę w pisanie każdej linii, którą piszę. Ale wierzę w pisanie w 100% testowej wersji wszystkich funkcji, które chcę zapewnić (nawet w przypadku dodatkowych fajnych funkcji, które przyjechałem ze sobą i które nie były omawiane podczas spotkań).

Nie dbam o to, czy będę miał kod, który nie jest objęty testami, ale dbałbym o to, czy zmienię kod i ostatecznie zachowam się inaczej. Dlatego 100% zakres funkcjonalności jest moim jedynym celem.


4
To fantastyczna odpowiedź. Kod, który spełnia jego wymagania, jest o wiele bardziej wartościowym celem niż kod, który spełnia niektóre arbitralne wskaźniki zasięgu LoC.
Dawood ibn Kareem

46
Jeśli możesz zapewnić całą funkcjonalność bez naciskania wszystkich wierszy kodu, co tam robią te dodatkowe wiersze kodu?
Jens Timmerman,

4
@JensTimmerman teoretycznie masz rację. Jednak pokrycie kodu w 100% jest zbyt drogie w stosunku do czasu i zmuszenie mojego zespołu do tego nie tylko demotywuje ich, ale także sprawia, że ​​mój projekt jest realizowany w terminie. Lubię być gdzieś pośrodku, a testowanie funkcjonalności (nazwij to testowaniem integracji) jest tym, co sprawia mi przyjemność. Jakiego kodu nie testuję? Obsługa wyjątków technicznych, kontrole (zakres / parametr), które mogą być potrzebne. Krótko mówiąc, wszystkie techniczne instalacje, które nauczyłem się stosować na podstawie własnego doświadczenia lub najlepszych praktyk, o których czytałem.
tofi9

2
Posunąłem się o krok dalej, tworząc listę typowych sytuacji, które należy uwzględnić lub wykluczyć z testów. W ten sposób nigdy nie zmierzaliśmy w kierunku procentu, a raczej funkcjonalnego pokrycia wszystkich części działającej bazy kodu.
Skeeterdrums

58

Przyjęta odpowiedź ma sens - nie ma jednej liczby, która miałaby sens jako standard dla każdego projektu. Są projekty, które po prostu nie potrzebują takiego standardu. Tam, gdzie przyjęta odpowiedź jest niewystarczająca, moim zdaniem polega na opisaniu, w jaki sposób można podjąć taką decyzję dla danego projektu.

Spróbuję to zrobić. Nie jestem ekspertem w inżynierii testów i chętnie zobaczę bardziej świadomą odpowiedź.

Kiedy należy ustawić wymagania dotyczące zasięgu kodu

Po pierwsze, dlaczego miałbyś narzucić taki standard? Ogólnie rzecz biorąc, gdy chcesz wprowadzić empiryczne zaufanie do swojego procesu. Co rozumiem przez „pewność empiryczną”? Cóż, prawdziwa poprawność celu . W przypadku większości programów nie możemy tego wiedzieć na wszystkich wejściach, dlatego zgadzamy się z twierdzeniem, że kod jest dobrze przetestowany . Jest to bardziej poznawalne, ale wciąż jest subiektywnym standardem: zawsze będzie można dyskutować, czy go osiągnąłeś. Debaty te są przydatne i powinny się odbyć, ale także ujawniają niepewność.

Pokrycie kodu jest obiektywnym pomiarem: gdy zobaczysz raport pokrycia, nie będzie wątpliwości, czy standardy zostały spełnione. Czy to dowodzi poprawności? Wcale nie, ale ma wyraźny związek z tym, jak dobrze przetestowano kod, co z kolei jest naszym najlepszym sposobem na zwiększenie pewności co do jego poprawności. Pokrycie kodu jest mierzalnym przybliżeniem niezmiernych cech, na których nam zależy.

Niektóre szczególne przypadki, w których posiadanie standardu empirycznego może przynieść wartość dodaną:

  • Aby zadowolić interesariuszy. W przypadku wielu projektów istnieją różne podmioty zainteresowane jakością oprogramowania, które mogą nie być zaangażowane w codzienne opracowywanie oprogramowania (menedżerowie, kierownicy techniczni itp.) Mówiąc „napiszemy wszystko testy, których naprawdę potrzebujemy ”nie są przekonujące: albo muszą całkowicie ufać, albo weryfikować przy ciągłym ścisłym nadzorze (zakładając, że mają nawet techniczną wiedzę, aby to zrobić.) Zapewnienie mierzalnych standardów i wyjaśnienie, w jaki sposób uzasadnione przybliżenie rzeczywistych celów jest lepsze.
  • Aby znormalizować zachowanie zespołu. Poza stronami zainteresowanymi, jeśli pracujesz w zespole, w którym wiele osób pisze kod i testy, jest miejsce na dwuznaczność tego, co kwalifikuje się jako „dobrze przetestowane”. Czy wszyscy twoi koledzy mają takie samo pojęcie o tym, jaki poziom testowania jest wystarczająco dobry? Prawdopodobnie nie. Jak to pogodzisz? Znajdź wskaźnik, na który wszyscy się zgodzicie, i zaakceptuj go jako rozsądne przybliżenie. Jest to szczególnie (ale nie wyłącznie) przydatne w dużych zespołach, w których liderzy mogą na przykład nie mieć bezpośredniego nadzoru nad młodszymi programistami. Liczą się także sieci zaufania, ale bez obiektywnych pomiarów zachowanie grupy może stać się niespójne, nawet jeśli wszyscy działają w dobrej wierze.
  • Aby zachować uczciwość. Nawet jeśli jesteś jedynym programistą i jedynym interesariuszem swojego projektu, możesz mieć pewne cechy oprogramowania. Zamiast dokonywać bieżących subiektywnych ocen tego, jak dobrze przetestowane jest oprogramowanie (co wymaga pracy), możesz użyć pokrycia kodu jako rozsądnego przybliżenia i pozwolić, aby maszyny dokonały jego pomiaru.

Których wskaźników użyć

Pokrycie kodu nie jest pojedynczą miarą; istnieje kilka różnych sposobów pomiaru zasięgu. To, na którym możesz ustawić standard, zależy od tego, czego używasz w celu spełnienia tego standardu.

Użyję dwóch typowych wskaźników jako przykładów, kiedy możesz je wykorzystać do ustalenia standardów:

  • Zakres wyciągów : Jaki procent wyciągów wykonano podczas testowania? Przydatne, aby zorientować się w fizycznym pokryciu twojego kodu: Ile kodu, który napisałem, faktycznie przetestowałem?
    • Ten rodzaj pokrycia obsługuje słabszy argument dotyczący poprawności, ale jest również łatwiejszy do osiągnięcia. Jeśli używasz tylko pokrycia kodu, aby upewnić się, że wszystko jest testowane (a nie jako wskaźnik jakości testu poza tym), to pokrycie instrukcji jest prawdopodobnie wystarczające.
  • Zasięg gałęzi : czy istnieje logika rozgałęziania (np. An if), czy oceniono obie gałęzie? To daje lepsze zrozumienie logicznego zasięgu twojego kodu: Ile możliwych ścieżek może obrać mój kod po przetestowaniu?
    • Ten rodzaj pokrycia jest znacznie lepszym wskaźnikiem, że program został przetestowany na obszernym zestawie danych wejściowych. Jeśli używasz pokrycia kodu jako najlepszego empirycznego przybliżenia dla pewności co do poprawności, powinieneś ustanowić standardy na podstawie pokrycia oddziału lub podobnego.

Istnieje wiele innych wskaźników (pokrycie linii jest podobne do pokrycia wyciągu, ale daje na przykład różne wyniki liczbowe dla wyciągów wieloliniowych, na przykład; pokrycie warunkowe i pokrycie ścieżki jest podobne do pokrycia gałęzi, ale odzwierciedla bardziej szczegółowy widok możliwych permutacji wykonanie programu, które możesz napotkać).

Jaki procent wymagać

Na koniec wróć do pierwotnego pytania: Jeśli ustalisz standardy pokrycia kodu, jaka powinna być ta liczba?

Mam nadzieję, że w tym momencie jest jasne, że mówimy o przybliżeniu na początku, więc każda liczba, którą wybierzemy, będzie z natury przybliżona.

Niektóre liczby, które można wybrać:

  • 100% . Możesz to wybrać, ponieważ chcesz mieć pewność, że wszystko zostało przetestowane. Nie daje to żadnego wglądu w jakość testu, ale mówi, że jakiś test jakiejś jakości dotknął każdego stwierdzenia (lub oddziału itp.) Ponownie, to wraca do stopnia pewności: jeśli twoje pokrycie jest poniżej 100% , wiesz , że część podzbioru twojego kodu jest nieprzetestowana.
    • Niektórzy mogą twierdzić, że jest to głupie i powinieneś testować tylko te części kodu, które są naprawdę ważne. Twierdziłbym, że powinieneś również zachować tylko te części kodu, które są naprawdę ważne. Zasięg kodu można poprawić, usuwając również niesprawdzony kod.
  • 99% (lub 95%, inne liczby z wysokich lat dziewięćdziesiątych). Odpowiednie w przypadkach, gdy chcesz przekazać poziom pewności podobny do 100%, ale zostaw sobie margines, aby nie martwić się o trudny do przetestowania zakątek kod.
  • 80% . Widziałem tę liczbę kilka razy i nie do końca wiem, skąd pochodzi. Myślę , że może to być dziwne sprzeniewierzenie zasady 80-20; ogólnie rzecz biorąc, chodzi tutaj o pokazanie, że większość kodu jest testowana. (Tak, 51% byłoby również „najbardziej”, ale 80% lepiej odzwierciedla to, co większość ludzi rozumie przez większość). Jest to właściwe w przypadkach, gdy „dobrze przetestowane” nie ma wysokiego priorytetu (nie nie chcesz marnować wysiłku na testy o niskiej wartości), ale jest to na tyle priorytet, że nadal chciałbyś mieć jakiś standard.

Nie widziałem liczb poniżej 80% w praktyce i trudno mi sobie wyobrazić przypadek, w którym można by je ustawić. Rolą tych standardów jest zwiększenie pewności co do poprawności, a liczby poniżej 80% nie budzą szczególnego zaufania. (Tak, jest to subiektywne, ale znowu chodzi o to, aby dokonać subiektywnego wyboru raz, kiedy ustanawiasz standard, a następnie użyć obiektywnego pomiaru w przyszłości.)

Inne notatki

Powyższe zakłada, że ​​celem jest poprawność. Pokrycie kodu to tylko informacja; może to odnosić się do innych celów. Na przykład, jeśli obawiasz się o łatwość konserwacji, prawdopodobnie zależy ci na luźnym sprzężeniu, co można wykazać testowalnością, którą z kolei można zmierzyć (w niektórych modach) pokryciem kodu. Zatem standard pokrycia kodu stanowi empiryczną podstawę do przybliżenia jakości „łatwości konserwacji”.


Dobra odpowiedź. Czy możesz mi pomóc w znalezieniu zakresu funkcjonalności za pomocą testów jednostkowych? Jakieś narzędzia, które mogą pomóc mi to osiągnąć?
curlyreggie

2
Świetna odpowiedź. Jako jedyny koncentruje się na testowaniu jako problem zespołowy w środowisku przemysłowym. Nie wszystko oceniam, a mój zespół jest bardzo bystry, ale zielony. Ustawiłem procentowy poziom 90% na nowy projekt jako sprawdzian poczytalności dla młodszych deweloperów, nie dlatego, że uważam, że to „wystarczy”. „90%” i ​​„pozytywne, negatywne i zerowe” to łatwe mantry dla jasnych, młodych programistów, o których wiem, że wykonają dobrą robotę, ale nie mają doświadczenia, aby napisać ten dodatkowy przypadek testowy, który dokucza z tyłu twojego umysłu.
0x1mason

2
myślę, że to najlepsza dostępna odpowiedź.
bugkiller

27

Mój ulubiony kod to 100% z gwiazdką. Gwiazdka pojawia się, ponieważ wolę używać narzędzi, które pozwalają mi oznaczać niektóre linie jako linie „nie liczące się”. Jeśli pokryłem 100% linii, które się „liczą”, jestem skończony.

Podstawowym procesem jest:

  1. Piszę testy, aby wykonać wszystkie funkcje i przypadki, o których mogę pomyśleć (zwykle na podstawie dokumentacji).
  2. Korzystam z narzędzi pokrycia kodu
  3. Badam wszystkie linie lub ścieżki, które nie są objęte, i te, które uważam za nieistotne lub nieosiągalne (z powodu programowania obronnego) zaznaczam jako nie liczące się
  4. Piszę nowe testy, aby pokryć brakujące linie i poprawić dokumentację, jeśli te przypadki brzegowe nie są wymienione.

W ten sposób, jeśli ja i moi współpracownicy dodamy nowy kod lub zmienimy testy w przyszłości, istnieje jasna linia, która mówi nam, czy coś przeoczyliśmy - zasięg spadł poniżej 100%. Zapewnia również elastyczność w radzeniu sobie z różnymi priorytetami testowania.


3
@ErikE Asterix jest, oczywiście, krótkim, ale nieustraszonym wojownikiem z Galii, który tworzy wyjątki od monotonnej rzymskiej okupacji, dlatego też jego imię nazwano jego małym symbolem typograficznym. (Mówiąc poważniej, dziękuję, poprawiłem pisownię.)
tytuł z

3
Czy chciałbyś uwzględnić „narzędzia, które pozwalają [oznaczać] niektóre linie jako linie, które się nie liczą”?
domdambrogia

2
@domdambrogia Jako przykład w PHP, jeśli używasz biblioteki pokrycia kodu Bergmanna, napisz adnotację do linii, // @codeCoverageIgnorektóra zostanie wykluczona z pokrycia.
biskup

19

Chciałbym mieć kolejną anektodę na temat testu, którym chciałbym się podzielić.

Mamy ogromny projekt, w którym ponad twitter zauważyłem, że przy 700 testach jednostkowych mamy tylko 20% pokrycia kodu .

Scott Hanselman odpowiedział słowami mądrości :

Czy to PRAWO 20%? Czy to 20% odpowiada kodowi, który najbardziej uderzyli twoi użytkownicy? Możesz dodać jeszcze 50 testów i dodać tylko 2%.

Znowu wraca do mojego Testivus na temat odpowiedzi dotyczącej pokrycia kodu . Ile ryżu należy włożyć do garnka? To zależy.


Oczywiście musi tam być zdrowy rozsądek. Nie ma większego zastosowania, jeśli 50% testowanego kodu to komentarze.
rozsądek

2
Bardziej zależy to od ... czy twoje wydatki są wydawane na podstawową funkcjonalność aplikacji, czy też bezużytecznie testuje trywialne funkcje / przydatne?
Jon Limjap

wygląda na to, że znaczna część twojego kodu to albo podstawka, albo obsługa wyjątków, albo warunkowe „tryb debugowania”
Erik Aronesty

8

W przypadku dobrze zaprojektowanego systemu, w którym testy jednostkowe napędzały rozwój od samego początku, powiedziałbym, że 85% to dość niska liczba. Małe klasy zaprojektowane do testowania nie powinny być trudne do opisania lepiej.

Łatwo jest odrzucić to pytanie za pomocą:

  • Zakryte linie nie są równe testowanej logice i nie należy wczytywać zbyt wiele w procent.

To prawda, ale należy zwrócić uwagę na kilka ważnych kwestii dotyczących pokrycia kodu. Z mojego doświadczenia wynika, że ​​ta metryka jest właściwie bardzo przydatna, jeśli jest właściwie używana. Powiedziawszy to, nie widziałem wszystkich systemów i jestem pewien, że jest ich mnóstwo, w których trudno jest zobaczyć analizę pokrycia kodu dodającą jakąkolwiek rzeczywistą wartość. Kod może wyglądać tak różnie, a zakres dostępnych ram testowych może się różnić.

Ponadto moje rozumowanie dotyczy głównie dość krótkich pętli testowych. Dla produktu, który opracowuję, najkrótsza pętla sprzężenia zwrotnego jest dość elastyczna, obejmując wszystko, od testów klasowych po sygnalizację między procesami. Testowanie dostarczalnego produktu podrzędnego zwykle zajmuje 5 minut, a dla tak krótkiej pętli sprzężenia zwrotnego rzeczywiście można wykorzystać wyniki testu (a konkretnie metrykę pokrycia kodu, na którą tu patrzymy), aby odrzucić lub zaakceptować zatwierdzenia w repozytorium.

Korzystając z metryki pokrycia kodu, nie powinieneś mieć ustalonego (arbitralnego) procentu, który należy spełnić. Takie postępowanie nie daje moim zdaniem prawdziwych korzyści z analizy pokrycia kodu. Zamiast tego zdefiniuj następujące miary:

  • Low Water Mark (LWM), najniższa liczba odkrytych linii, jaką kiedykolwiek widziano w badanym systemie
  • High Water Mark (HWM), najwyższy procent pokrycia kodu, jaki kiedykolwiek zaobserwowano dla testowanego systemu

Nowy kod można dodać tylko wtedy, gdy nie przekroczymy LWM i nie zejdziemy poniżej HWM. Innymi słowy, nie można zmniejszyć zasięgu kodu i należy go pokryć nowym kodem. Zwróć uwagę, jak mówię, że powinno, a nie musi (wyjaśnione poniżej).

Ale czy to nie oznacza, że ​​nie będzie możliwe usunięcie starych, dobrze przetestowanych śmieci, do których nie będziesz już dłużej potrzebował? Tak i dlatego musisz być pragmatyczny w tych sprawach. Są sytuacje, w których reguły muszą zostać złamane, ale dla twojej typowej codziennej integracji z moich doświadczeń wynika, że ​​te wskaźniki są dość przydatne. Dają one następujące dwie implikacje.

  • Kod testowany jest promowany. Dodając nowy kod, naprawdę musisz dołożyć starań, aby kod był testowalny, ponieważ będziesz musiał spróbować pokryć to wszystko swoimi przypadkami testowymi. Testowalny kod jest zwykle dobrą rzeczą.

  • Z czasem zasięg testowy starszego kodu rośnie. Dodając nowy kod i nie będąc w stanie objąć go przypadkiem testowym, można zamiast tego spróbować zakodować trochę starszego kodu, aby obejść regułę LWM. To czasami konieczne oszustwo daje przynajmniej pozytywny efekt uboczny, że zasięg starszego kodu wzrośnie z czasem, co sprawia, że ​​pozornie rygorystyczne egzekwowanie tych zasad jest w praktyce bardzo pragmatyczne.

I znowu, jeśli pętla sprzężenia zwrotnego jest zbyt długa, ustawienie czegoś takiego w procesie integracji może być całkowicie niepraktyczne.

Chciałbym również wspomnieć o dwóch innych ogólnych zaletach metryki pokrycia kodu.

  • Analiza pokrycia kodu jest częścią dynamicznej analizy kodu (w przeciwieństwie do analizy statycznej, tj. Lint). Problemy wykryte podczas dynamicznej analizy kodu (przez narzędzia takie jak rodzina purify , http://www-03.ibm.com/software/products/en/rational-purify-family ) to takie rzeczy jak niezainicjowane odczyty pamięci (UMR), wycieki pamięci itp. Problemy te można znaleźć tylko wtedy, gdy kod jest objęty wykonanym przypadkiem testowym . Kod, który jest najtrudniejszy do pokrycia w przypadku testowym, to zwykle przypadki nienormalne w systemie, ale jeśli chcesz, aby system zawiódł w sposób płynny (tj. Śledzenie błędów zamiast awarii), możesz zechcieć włożyć trochę wysiłku w pokrycie przypadków nienormalnych także w dynamicznej analizie kodu. Przy odrobinie pecha UMR może doprowadzić do awarii lub pogorszenia się.

  • Ludzie są dumni z zachowania 100% nowego kodu, a ludzie dyskutują o testowaniu problemów z podobną pasją jak inne problemy z implementacją. Jak można napisać tę funkcję w bardziej sprawdzalny sposób? Jak poszedłbyś na próbę pokrycia tego nienormalnego przypadku itp.

I negatywne, dla kompletności.

  • W dużym projekcie z wieloma zaangażowanymi programistami każdy z pewnością nie będzie geniuszem testowym. Niektóre osoby używają metryki pokrycia kodu jako dowodu, że kod jest testowany i jest to bardzo dalekie od prawdy , jak wspomniano w wielu innych odpowiedziach na to pytanie. To JEDNA miara, która może przynieść dobre korzyści, jeśli jest właściwie używana, ale jeśli jest niewłaściwie używana, może w rzeczywistości prowadzić do złych testów. Poza bardzo cennymi efektami ubocznymi wspomnianymi powyżej, ukryta linia pokazuje tylko, że testowany system może osiągnąć tę linię dla niektórych danych wejściowych i że może zostać wykonany bez zawieszenia lub awarii.

7

Gdyby to był idealny świat, 100% kodu byłoby objęte testami jednostkowymi. Ponieważ jednak NIE jest to idealny świat, jest to kwestia tego, na co masz czas. W związku z tym zalecam mniejszą koncentrację na określonym odsetku, a bardziej na obszarach krytycznych. Jeśli Twój kod jest dobrze napisany (lub przynajmniej jego uzasadniony faks), powinno być kilka kluczowych punktów, w których interfejsy API są narażone na inny kod.

Skoncentruj swoje wysiłki testowe na tych interfejsach API. Upewnij się, że interfejsy API są 1) dobrze udokumentowane i 2) napisane przypadki testowe pasujące do dokumentacji. Jeśli oczekiwane wyniki nie zgadzają się z dokumentami, oznacza to błąd w kodzie, dokumentacji lub przypadkach testowych. Wszystkie są dobre do sprawdzenia.

Powodzenia!


6

Wiele sklepów nie docenia testów, więc jeśli jesteś powyżej zera, przynajmniej doceniasz wartość - więc prawdopodobnie niezerowe nie jest złe, ponieważ wiele wciąż jest zerowych.

W świecie .Net ludzie często podają 80% za uzasadnione. Ale mówią to na poziomie rozwiązania. Wolę mierzyć na poziomie projektu: 30% może być w porządku w przypadku projektu interfejsu użytkownika, jeśli masz Selenium itp. Lub testy ręczne, 20% w przypadku projektu warstwy danych może być w porządku, ale 95% + może być całkiem osiągalne dla firmy warstwa reguł, jeśli nie jest to absolutnie konieczne. Tak więc całkowity zasięg może wynosić, powiedzmy, 60%, ale krytyczna logika biznesowa może być znacznie wyższa.

Słyszałem także: aspiruj do 100%, a osiągniesz 80%; ale dąż do 80%, a trafisz 40%.

Konkluzja: Zastosuj regułę 80:20 i pozwól, aby liczba błędów aplikacji poprowadziła Cię.



4

85% byłoby dobrym miejscem startowym dla kryteriów meldowania.

Prawdopodobnie wybrałbym wiele wyższych słupków dla kryteriów wysyłki - w zależności od krytyczności testowanych podsystemów / komponentów.


54
Jak doszedłeś do tego odsetka?
rozsądek

Jako przypis - może być nieporządny w przypadku projektów, w których automatyzacja jest trudna - jak zawsze pragmatyczny w kwestii tego, co osiągalne czy pożądane.
stephbu

4
Głównie poprzez eksperymenty. Osiągnięcie pokrycia kodu do 80-90% jest dość łatwe w przypadku testów jednostkowych związanych z programistami - osiągnięcie wyższego poziomu zwykle wymaga interwencji boskiego testu - lub naprawdę prostych ścieżek kodu.
stephbu

1
Zaczynam zwykle od 1) głównych ścieżek kodu środowiska wykonawczego 2) oczywistych przypadków wyjątków, które jawnie wrzucam 3) przypadków warunkowych, które kończą się „awarią” To zwykle przenosi cię do zakresu 70-80 Następnie wackamole, błędy i regresje dla przypadków narożnych, parametr fuzzing itp. Refaktoryzacja w celu umożliwienia wstrzykiwania metod itp. Zasadniczo daję co najmniej tyle samo czasu na pisanie / refaktoryzację testów związanych z programistą, jak sam główny kod.
stephbu

4

Korzystam z cobertury i niezależnie od wartości procentowej zalecałbym aktualizowanie wartości w zadaniu sprawdzania cobertury. Co najmniej zwiększaj totallinerate i totalbranchrate do poziomu nieco poniżej obecnego zasięgu, ale nigdy nie obniżaj tych wartości. Do tego zadania należy również przypisać właściwość niepowodzenia kompilacji Ant. Jeśli kompilacja nie powiedzie się z powodu braku zasięgu, znasz kod dodany przez kogoś, ale go nie przetestował. Przykład:

<cobertura-check linerate="0"
                 branchrate="0"
                 totallinerate="70"
                 totalbranchrate="90"
                 failureproperty="build.failed" />

4

Kiedy myślę, że mój kod nie jest wystarczająco przetestowany jednostkowo i nie jestem pewien, co przetestować w następnej kolejności, używam pokrycia, aby pomóc mi zdecydować, co przetestować w następnej kolejności.

Jeśli zwiększę zasięg w teście jednostkowym - wiem, że ten test jednostkowy jest coś wart.

Dotyczy to kodu, który nie jest objęty, objęty w 50% lub w 97%.


3
Całkowicie się nie zgadzam. Test jednostkowy jest wart czegoś, tylko jeśli istnieje szansa, że ​​wykryje błąd (błąd, który istnieje teraz lub błąd regresji w przyszłości); lub jeśli pomoże to udokumentować zachowanie twojej klasy. Jeśli metoda jest tak prosta, że ​​tak naprawdę nie może zawieść, na przykład getter jednoliniowy, oznacza to, że istnieje zerowa wartość dla dostarczenia jej testu jednostkowego.
Dawood ibn Kareem

6
Miałem błędy w pobierających jeden wiersz. Z mojego doświadczenia wynika, że ​​nie ma kodu wolnego od błędów. Nie ma metody, która naprawdę nie mogłaby zawieść.
brickner

1
Zakładając, że twój geter jednowierszowy jest używany przez inny kod, który obejmujesz, a testy tego kodu przebiegają pomyślnie, wtedy pośrednio obejmujesz również getter jednowierszowy. Jeśli nie używasz modułu pobierającego, co on robi w kodzie? Zgadzam się z Davidem Wallace… nie ma potrzeby bezpośredniego testowania prostych funkcji pomocnika, które są używane gdzie indziej, jeśli kod i testy zależne od pomocnika nie pokazują, że może być z tym problem.
Lowell Montgomery

@ LowellMontgomery i co jeśli test drugiego kodu nie powiedzie się z powodu tego gettera jednowierszowego (który nie został przetestowany)? Gdyby istniał test dla jednej linijki, znacznie łatwiej byłoby dotrzeć do przyczyny niepowodzenia. Robi się naprawdę źle, gdy w kilku różnych miejscach używa się setek niesprawdzonych jednowarstwowych.
Daniel

Założeniem były testy z wykorzystaniem jednego getra z jednym wierszem. Jeśli się nie udało (np. Gdy próbujesz użyć wartości zwracanej z gettera jednowierszowego), możesz to rozwiązać. Ale chyba, że ​​istnieje naprawdę naglący powód bycia tak paranoikiem, musisz gdzieś wytyczyć granicę. Z mojego doświadczenia wynika, że ​​muszę nadać priorytet temu, co pochłania mój czas i uwagę, a naprawdę proste „osoby pobierające” (które działają) nie potrzebują osobnych testów. Ten czas można poświęcić na ulepszenie innych testów lub pełne pokrycie kodu, który jest bardziej podatny na niepowodzenie. (tzn. podtrzymuję swoje oryginalne stanowisko z Davidem Wallace'em).
Lowell Montgomery

4

Wolę robić BDD, który wykorzystuje kombinację automatycznych testów akceptacyjnych, ewentualnie innych testów integracyjnych i testów jednostkowych. Pytanie brzmi: jaki powinien być docelowy zasięg zautomatyzowanego zestawu testów jako całości.

Poza tym odpowiedź zależy od metodologii, języka oraz narzędzi testowania i pokrycia. Robiąc TDD w Ruby lub Python, nie jest trudno utrzymać 100% zasięgu i warto to zrobić. Znacznie łatwiej jest zarządzać 100% pokryciem niż 90-procentowy zasięg. Oznacza to, że o wiele łatwiej jest wypełnić luki pokrycia, gdy się pojawiają (a przy wykonywaniu studni TDD luki pokrycia są rzadkie i zwykle warte poświęcenia czasu), niż zarządzanie listą luk pokrycia, których jeszcze nie dotarłeś i których brakuje regresje z powodu stałego tła odkrytego kodu.

Odpowiedź zależy również od historii twojego projektu. Przekonałem się, że powyższe jest praktyczne w projektach zarządzanych w ten sposób od samego początku. Znacząco poprawiłem zasięg dużych, starszych projektów i warto było to zrobić, ale nigdy nie uważałem za praktyczne wracać i wypełniać każdą lukę pokrycia, ponieważ stary nieprzetestowany kod nie jest wystarczająco dobrze zrozumiany, aby zrobić to poprawnie i szybko.


3

Jeśli przeprowadzałeś testy jednostkowe przez przyzwoity czas, nie widzę powodu, aby nie zbliżać się do 95% +. Jednak przynajmniej zawsze pracowałem z 80%, nawet jeśli dopiero zaczynasz testować.

Liczba ta powinna zawierać tylko kod napisany w projekcie (z wyłączeniem frameworków, wtyczek itp.), A może nawet wykluczać niektóre klasy złożone w całości z kodu napisanego z wywołań kodu zewnętrznego. Tego rodzaju połączenie powinno być wyśmiewane / karczowane.


3

Ogólnie rzecz biorąc, z kilku artykułów na temat najlepszych praktyk inżynieryjnych, które przeczytałem, 80% na nowy kod w testach jednostkowych jest punktem, który daje najlepszy zwrot. Powyżej tego CC% daje mniej wad w stosunku do nakładanego wysiłku. Jest to najlepsza praktyka stosowana przez wiele dużych korporacji.

Niestety większość z tych wyników ma charakter wewnętrzny dla firm, więc nie ma literatury publicznej, na którą mógłbym cię wskazać.


3

Zakres kodu jest świetny, ale tylko o ile korzyści, które z niego czerpiesz, przewyższają koszty / wysiłek związany z jego osiągnięciem.

Od pewnego czasu pracujemy na poziomie 80%, jednak właśnie postanowiliśmy porzucić to i zamiast tego bardziej skupić się na testowaniu. Koncentrując się na złożonej logice biznesowej itp.,

Ta decyzja została podjęta ze względu na coraz więcej czasu spędzonego na pogoni za pokryciem kodu i utrzymywaniu istniejących testów jednostkowych. Czuliśmy, że doszliśmy do punktu, w którym korzyść, którą otrzymaliśmy z zakresu naszego kodu, została uznana za mniejszą niż wysiłek, jaki musieliśmy włożyć w to, aby to osiągnąć.


2

Krótka odpowiedź: 60–80%

Długa odpowiedź: myślę, że to całkowicie zależy od charakteru twojego projektu. Zazwyczaj zaczynam projekt od testowania jednostkowego każdego praktycznego elementu. Do pierwszego „wydania” projektu powinieneś mieć całkiem niezły procent bazowy na podstawie rodzaju wykonywanego programowania. W tym momencie możesz rozpocząć „wymuszanie” minimalnego pokrycia kodu.


2

Sprawdź Crap4j . Jest to nieco bardziej wyrafinowane podejście niż proste pokrycie kodu. Łączy pomiary pokrycia kodu z pomiarami złożoności, a następnie pokazuje, który złożony kod nie jest obecnie testowany.


2

Moja odpowiedź na tę zagadkę to 100% pokrycie linii kodu, który można przetestować, i 0% pokrycie linii kodu, którego nie można przetestować.

Moja obecna praktyka w Pythonie polega na dzieleniu modułów .py na dwa foldery: app1 / i app2 /, a po uruchomieniu testów jednostkowych obliczyć pokrycie tych dwóch folderów i wizualnie sprawdzić ( pewnego dnia muszę zautomatyzować), czy app1 ma 100% pokrycia i app2 ma 0% zasięgu.

Kiedy / jeśli stwierdzę, że te liczby różnią się od standardu, badam i zmieniam projekt kodu, aby zasięg był zgodny ze standardem.

Oznacza to, że mogę zalecić uzyskanie 100% pokrycia linii kodu biblioteki.

Od czasu do czasu sprawdzam także aplikację2 /, aby sprawdzić, czy mogę tam przetestować dowolny kod, a jeśli mogę, mogę przenieść go do aplikacji 1 /

Teraz nie martwię się zbytnio o łączny zasięg, ponieważ może się to bardzo różnić w zależności od wielkości projektu, ale ogólnie widziałem 70% do ponad 90%.

Dzięki pythonowi powinienem być w stanie opracować test dymu, który mógłby automatycznie uruchamiać moją aplikację podczas pomiaru zasięgu i mam nadzieję, że zyskam łączną wartość 100%, łącząc test dymu z najmniejszymi liczbami.


2

Oglądanie relacji z innej perspektywy: Dobrze napisany kod z wyraźnym przepływem kontroli jest najłatwiejszy do pokrycia, najłatwiejszy do odczytania i zwykle najmniej wadliwy kod. Pisząc kod z myślą o przejrzystości i pokryciu oraz pisząc testy jednostkowe równolegle z kodem, otrzymujesz najlepsze wyniki IMHO.


2

Moim zdaniem odpowiedź brzmi: „To zależy od tego, ile masz czasu”. Staram się osiągnąć 100%, ale nie robię zamieszania, jeśli nie dostanę go z czasem.

Kiedy piszę testy jednostkowe, noszę inną czapkę niż czapkę, którą noszę podczas opracowywania kodu produkcyjnego. Myślę o tym, co twierdzi testowany kod i jakie sytuacje mogą go złamać.

Zwykle przestrzegam następujących kryteriów lub zasad:

  1. Test jednostkowy powinien być formą dokumentacji na temat oczekiwanego zachowania moich kodów, tj. oczekiwane dane wyjściowe przy określonych danych wejściowych i wyjątki, które mogą generować, które klienci mogą chcieć wyłapać (co powinni wiedzieć użytkownicy mojego kodu?)

  2. Test jednostkowy powinien mi pomóc odkryć, co się stanie, jeśli jeszcze nie pomyślałem. (Jak uczynić mój kod stabilnym i niezawodnym?)

Jeśli te dwie reguły nie zapewniają 100% zasięgu, niech tak będzie. Ale raz mam czas, analizuję odkryte bloki i linie i stwierdzam, czy nadal istnieją przypadki testowe bez testów jednostkowych, czy też kod należy przefaktoryzować, aby wyeliminować niepotrzebne kody.


1

To zależy w dużej mierze od twojej aplikacji. Na przykład niektóre aplikacje składają się głównie z kodu GUI, którego nie można przetestować jednostkowo.


5
Prawdopodobnie powinieneś użyć Model View Presenter dla swojego interfejsu użytkownika, jeśli jesteś w środowisku TDD.
Charles Graham

1

Nie sądzę, żeby istniała taka zasada czarno-biała.
Kod powinien zostać przejrzany, ze szczególnym uwzględnieniem najważniejszych szczegółów.
Jeśli jednak nie został przetestowany, ma błąd!


Nie chcę reguły, po prostu informacje zwrotne na temat osobistych doświadczeń dotyczących korelacji między procentem pokrycia kodu a efektywnością testu jednostkowego.
rozsądek

1

W zależności od krytyczności kodu, gdziekolwiek od 75% -85% jest dobrą regułą. Kod wysyłki należy zdecydowanie przetestować dokładniej niż w domowych instalacjach itp.


1

Musi to zależeć od tego, na jakim etapie cyklu rozwoju aplikacji jesteś.

Jeśli jesteś w fazie projektowania i masz już zaimplementowany kod, a dopiero teraz zdajesz sobie sprawę, że musisz pomyśleć o pokryciu kodu, musisz sprawdzić swój obecny zasięg (jeśli istnieje), a następnie użyć tej linii bazowej, aby ustawiać kamienie milowe w każdym sprincie (lub średni wzrost w okresie sprintu), co oznacza przyjmowanie długu kodu przy jednoczesnym dostarczaniu wartości dla użytkownika końcowego (przynajmniej z mojego doświadczenia użytkownik końcowy nie obchodzi ani trochę, jeśli zwiększysz test zasięg, jeśli nie widzą nowych funkcji).

W zależności od domeny strzelanie do 95% nie jest nierozsądne, ale muszę powiedzieć, że średnio patrzysz na średni przypadek od 85% do 90%.


1

Myślę, że najlepszym objawem prawidłowego pokrycia kodu jest to, że ilość konkretnych problemów, które testy jednostkowe pomagają rozwiązać, w rozsądnym stopniu odpowiada rozmiarowi kodu testów jednostkowych, który stworzyłeś.


1

Myślę, że najważniejsza może być znajomość trendu pokrycia w czasie i zrozumienie przyczyn zmian w tym trendzie. To, czy postrzegasz zmiany w trendach jako dobre czy złe, będzie zależeć od analizy przyczyny.


0

Celowaliśmy w> 80% do kilku dni wstecz, ale po tym, jak użyliśmy dużo Wygenerowanego kodu, nie dbamy o% wieku, ale raczej zachęcamy recenzenta do sprawdzenia wymaganego zakresu.


0

Z postu Testivus uważam, że kontekstem odpowiedzi powinien być drugi programista. Powiedziawszy to z praktycznego punktu widzenia, potrzebujemy parametrów / celów, do których należy dążyć. Uważam, że można to „przetestować” w procesie zwinnym, analizując kod, który mamy architekturę, funkcjonalność (historie użytkowników), a następnie wymyślamy liczbę. Na podstawie moich doświadczeń w dziedzinie telekomunikacji powiedziałbym, że 60% to dobra wartość do sprawdzenia.

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.