Podczas tworzenia oprogramowania nie sposób uniknąć błędów. Mogą one przyjmować różne formy, od niepoprawnej składni, poprzez błędy logiczne, problemy z wykonaniem, aż po kwestie związane z wydajnością, danymi czy nawet luki bezpieczeństwa.
Biorąc pod uwagę powszechność błędów w procesie tworzenia oprogramowania, testowanie staje się kluczowym etapem tego procesu. Dobre, efektywne testy gwarantują nie tylko wysoką jakość produktu, który spełnia potrzeby użytkowników, ale również zapewniają zgodność z regulacjami oraz minimalizują potencjalne luki, które mogłyby zostać wykorzystane przez osoby trzecie.
Testowanie oprogramowania może obejmować różnorodne metody, takie jak testy automatyczne, jednostkowe, integracyjne, a także testy całego systemu.
Jednak pojawia się istotne pytanie: jak możemy ocenić, czy oprogramowanie zostało gruntownie przetestowane? Czy przeprowadzone testy są wystarczające?
Czy każdy fragment kodu został dokładnie przeanalizowany, czy też istnieją obszary pominięte podczas testowania?
Te wątpliwości są naturalne podczas procesu testowania, dlatego tak ważne jest monitorowanie pokrycia kodu.
Pokrycie kodu to metryka, która informuje nas, jaka część kodu została faktycznie uruchomiona, a tym samym przetestowana, w ramach przeprowadzonych testów. Wynik wyraża się zazwyczaj w procentach.
Ten procentowy wskaźnik ukazuje, jaki odsetek kodu został objęty naszymi testami. Przykładowo, osiągnięcie 60% pokrycia kodu oznacza, że aż 40% kodu nie zostało poddane testom, co stwarza ryzyko występowania błędów i luk w zabezpieczeniach w tych nieprzetestowanych obszarach.
Dzięki analizie pokrycia kodu, możemy ocenić skuteczność i kompletność naszych testów. Pozwala to na gruntowne i kompleksowe przetestowanie oprogramowania przed jego publicznym wydaniem, co znacząco redukuje liczbę błędów w wersji produkcyjnej i minimalizuje negatywny wpływ na doświadczenia użytkowników.
Chociaż stuprocentowe pokrycie kodu nie jest gwarancją braku błędów, to dążenie do jego jak najwyższej wartości jest istotne w zapewnieniu efektywnego testowania oprogramowania.
W sektorach krytycznych, takich jak lotnictwo czy medycyna, gdzie błędy w oprogramowaniu mogą mieć tragiczne konsekwencje, regulacje często wymagają stuprocentowego pokrycia kodu.
Rodzaje wskaźników pokrycia kodu
Podczas testowania oprogramowania można analizować różne rodzaje metryk pokrycia kodu. Najczęściej spotykane to:
- Pokrycie instrukcji – określa, jaki procent wykonywalnych instrukcji w kodzie źródłowym został uruchomiony podczas testów.
- Pokrycie funkcji – mierzy, jaki odsetek zdefiniowanych funkcji został wywołany w trakcie testowania.
- Pokrycie rozgałęzień – analizuje procent wykonanych rozgałęzień lub możliwych ścieżek wynikających z punktów decyzyjnych w kodzie. Ma na celu sprawdzenie, czy wszystkie warianty wynikające z instrukcji warunkowych (if, switch, if-else) zostały przetestowane.
- Pokrycie warunków – sprawdza, jaki procent wyrażeń logicznych został przetestowany zarówno dla wartości prawdziwych, jak i fałszywych.
- Pokrycie pętli – mierzy, jaki odsetek pętli w kodzie źródłowym został wykonany podczas testów.
- Pokrycie ścieżek – bada, jaki procent wszystkich możliwych ścieżek wykonania kodu źródłowego został przetestowany.
Wymienione metryki są zazwyczaj zawarte w raporcie pokrycia kodu.
Najlepsze praktyki dotyczące pokrycia kodu
Istnieją sprawdzone metody, które warto stosować podczas analizy pokrycia kodu, aby zapewnić jego skuteczność i wysoką jakość. Do najważniejszych należą:
Wyznaczanie jasnych celów pokrycia
Przed rozpoczęciem testowania oprogramowania, warto ustalić docelowe wartości pokrycia dla każdej istotnej metryki. Dzięki temu nie tylko określimy jasne cele testowania, ale także zredukujemy liczbę defektów w oprogramowaniu. Ukierunkowanie działań zespołu na zwiększenie pokrycia kodu zapewni również, że testowanie oprogramowania otrzyma należytą uwagę w całym procesie jego tworzenia.
Koncentracja na jakości testów
Należy pamiętać, że pokrycie kodu jedynie informuje o procencie kodu, który został przetestowany, nie dając gwarancji, że testy te zostały przeprowadzone prawidłowo lub że oprogramowanie jest wolne od błędów. Dlatego zamiast skupiać się jedynie na osiągnięciu 100% pokrycia, należy przede wszystkim dążyć do tworzenia skutecznych, wysokiej jakości testów, które rzetelnie sprawdzają działanie oprogramowania i wnoszą realną wartość.
Zwiększanie pokrycia kodu w często modyfikowanych obszarach
Osiągnięcie wysokiego poziomu pokrycia kodu w dużych projektach może być wyzwaniem. Warto jednak dążyć do stopniowej poprawy tego wskaźnika z czasem.
Dobrym rozwiązaniem jest wprowadzenie wymogu wysokiego pokrycia kodu (powyżej 90%) dla każdej nowej zmiany w kodzie.
Wymuszanie pokrycia kodu na poziomie każdej zmiany w projekcie jest nie tylko realistyczne i wykonalne, ale również zapewnia, że wszelkie nowe modyfikacje w oprogramowaniu są bardzo dobrze przetestowane.
Analiza danych dotyczących pokrycia kodu
Wykorzystuj dane z pokrycia kodu do identyfikacji obszarów, które wymagają dodatkowego testowania, i kieruj przyszłe działania testowe na obszary z niskim pokryciem.
Analizując dane dotyczące pokrycia, łatwo można zlokalizować krytyczne części aplikacji, które nie zostały jeszcze przetestowane i skupić się na ich dokładnym sprawdzeniu. Takie podejście prowadzi do powstania lepiej przetestowanego oprogramowania, obarczonego mniejszą ilością błędów.
Pokrycie kodu a pokrycie testów
Chociaż oba terminy odnoszą się do oceny skuteczności testów, pokrycie kodu i pokrycie testów różnią się w kontekście ich zastosowania i mierzonych aspektów.
Pokrycie testów to miara, która określa, w jakim stopniu napisane testy obejmują wymagania oprogramowania. Obejmuje testowanie każdego wymagania i pomaga ustalić, czy oprogramowanie zostało odpowiednio zweryfikowane pod kątem ich spełnienia.
Wyniki pokrycia testów prezentują procent wymagań, które zostały poddane testowaniu. Pokrycie testów jest zazwyczaj domeną specjalistów ds. zapewnienia jakości.
Z kolei pokrycie kodu jest metryką służącą do oceny procentu kodu źródłowego, który został wykonany podczas testów.
Wyniki pokrycia kodu informują, w jakim stopniu instrukcje, funkcje, ścieżki, pętle, rozgałęzienia i warunki w kodzie źródłowym zostały uruchomione przez testy jednostkowe. Pokrycie kodu służy do oceny, jak dobrze napisane testy pokrywają kod źródłowy i jest domeną programistów.
Pokrycie kodu jest istotnym wskaźnikiem w procesie testowania oprogramowania. Poniżej znajduje się lista narzędzi, które pomogą Ci w jego analizie:
Clover
Clover to otwartoźródłowe narzędzie do analizy pokrycia kodu, stworzone przez australijską firmę Atlassian, która specjalizuje się w tworzeniu narzędzi dla zespołów programistycznych. Zostało napisane w całości w języku Java i może działać na dowolnym systemie operacyjnym, który spełnia wymagania środowiska Java Runtime Environment.
Clover pozwala na analizę pokrycia kodu napisanego w językach Java, Groovy lub AspectJ. Współpracuje z frameworkami testowymi, takimi jak JUnit, TestNG i Spock, a także integruje się ze środowiskami IDE, takimi jak IntelliJ IDEA i Eclipse.
Za pomocą Clover można mierzyć wskaźniki pokrycia kodu, takie jak metoda, instrukcja, gałąź, pokrycie globalne i na test.
Na podstawie wyników analizy, Clover generuje wysoce konfigurowalne raporty HTML, które pokazują wyniki pokrycia kodu, obszary największego ryzyka w oprogramowaniu i mogą być wykorzystane do optymalizacji testów.
Raporty można generować również w formatach PDF, XML, JSON lub jako zwykły tekst. Kluczową zaletą Clover jest możliwość integracji z wieloma różnymi narzędziami oraz jego ciągły rozwój.
JaCoCo
JaCoCo to bezpłatna biblioteka do analizy pokrycia kodu dla języka Java, opracowana przez zespół EclEmma. Jest zaimplementowana w EclEmma, która jest bezpłatnym narzędziem do pokrycia kodu Java dla Eclipse IDE.
JaCoCo oferuje szczegółową analizę pokrycia, której wyniki są natychmiast podsumowywane i wyróżniane w edytorze kodu źródłowego Java, pozwalając użytkownikom na wgląd w pokrycie do poziomu metody.
Wyniki prezentowane są za pomocą konfigurowalnego kodu kolorystycznego, który wyróżnia linie kodu, które zostały w pełni, częściowo lub wcale nieobjęte testami. Pozwala na łączenie i uwzględnianie różnych przebiegów testów w celu uzyskania całkowitego pokrycia kodu źródłowego.
JaCoCo jest lekkim narzędziem, które nie wymaga modyfikacji projektów ani dodatkowej konfiguracji do analizy pokrycia kodu.
Cobertura
Cobertura to bezpłatne, otwartoźródłowe narzędzie do analizy pokrycia kodu w języku Java, oparte na Jcoverage. Można go używać samodzielnie, za pośrednictwem skryptu Ant lub jako wtyczki Maven. Najczęstszym sposobem korzystania z Cobertury jest użycie wtyczki Maven.
Cobertura mierzy procent linii lub rozgałęzień, które zostały wykonane podczas testów kodu źródłowego w języku Java. Dostarcza metryki takie jak pokrycie linii, czyli procent instrukcji wykonanych podczas testów, oraz pokrycie gałęzi, czyli procent pokrytych gałęzi.
Pokazuje również współczynnik złożoności, który rośnie wraz ze wzrostem liczby rozgałęzień w kodzie Java.
Wyniki pokrycia kodu prezentowane są w formacie HTML lub XML, wskazując nieprzetestowane fragmenty kodu. Oprócz prezentowania wyników pokrycia testów, Cobertura może być wykorzystywana do lokalizowania nieprzetestowanego kodu, błędów, a także do identyfikowania niedostępnego kodu.
Stambuł
Istanbul to narzędzie do analizy pokrycia kodu dla kodu JavaScript, z obsługą ES6+. Można je zainstalować w każdym projekcie JavaScript jako zależność programistyczną, za pomocą menedżera pakietów węzłów (npm).
Istanbul dostarcza metryki pokrycia kodu, takie jak instrukcja, rozgałęzienie, funkcja i pokrycie linii. Wskazuje również linie w kodzie źródłowym, które nie zostały objęte testami. Działa poprzez dodawanie liczników linii do kodu JavaScript, dzięki czemu może śledzić, w jakim stopniu testy jednostkowe wykonują kod źródłowy.
Wyniki pokrycia kodu generowane przez Istanbul mogą być wyświetlane w terminalu lub w formacie HTML. Dodatkowo, Istanbul obsługuje aplikacje tworzące podprocesy oraz mapowanie zakresu projektów Babel i TypeScript.
Pytest-cov
Pytest-cov to bezpłatna wtyczka do Pythona, która służy do generowania raportów pokrycia kodu dla projektów napisanych w tym języku. Instaluje się ją za pomocą instalatora pakietów Pythona Pip i obsługuje z poziomu wiersza poleceń.
Raport pokrycia kodu generowany przez Pytest-cov pokazuje instrukcje w projekcie, które nie zostały objęte testami oraz procent pokrycia, wskazujący odsetek kodu Pythona, który został przetestowany.
Pytest-cov oferuje obsługę podprocesów, obsługę xdist oraz spójne zachowanie pytest. Domyślnie, przy przeprowadzaniu testów, Pytest-cov usuwa istniejące pliki z danymi pokrycia, aby zapewnić świeże dane dla każdego nowego uruchomienia. Umożliwia jednak również łączenie wyników testów z poprzednich przebiegów.
coverage.py
Coverage.py to narzędzie do analizy pokrycia kodu dla programów w Pythonie, które instaluje się w projektach z użyciem pip.
Domyślnie mierzy pokrycie linii lub instrukcji i dostarcza wyniki pokazujące liczbę instrukcji w programie, pominięte instrukcje w testach oraz procentowe pokrycie. Wskazuje również linie w kodzie źródłowym Pythona, które nie zostały przetestowane. Opcjonalnie, można go również skonfigurować do pomiaru pokrycia gałęzi w programach Pythona.
Coverage.py może być także wykorzystane do określenia, które testy uruchomiły poszczególne linie w kodzie źródłowym. Raporty pokrycia kodu mogą być generowane w terminalu, jak również w formatach HTML, XML, JSON i LCOV.
SimpleCov
SimpleCov to narzędzie do analizy pokrycia kodu dla języka programowania Ruby. Wykorzystuje wbudowaną bibliotekę pokrycia Ruby do zbierania danych, które mogą być wykorzystane do określenia pokrycia kodu po uruchomieniu testów.
Największą zaletą SimpleCov jest sposób prezentacji wyników pokrycia kodu. Łączy on wyniki z różnych rodzajów przeprowadzonych testów, dzięki czemu generowany raport pokazuje wyniki ze wszystkich testów, co ułatwia identyfikację nieprzetestowanych części kodu.
SimpleCov formatuje również kod źródłowy za pomocą kodów kolorystycznych, które pomagają w łatwej identyfikacji przetestowanych i nieprzetestowanych fragmentów kodu. Domyślnie SimpleCov mierzy i raportuje pokrycie linii. Można go jednak skonfigurować tak, aby mierzył i raportował również pokrycie gałęzi.
Głęboka osłona
Deep Cover to precyzyjne narzędzie do analizy pokrycia kodu dla kodu Ruby. Oferuje bardziej dokładne raporty pokrycia linii, zapewniając, że linia kodu jest uważana za pokrytą tylko wtedy, gdy jest wykonana w całości, a nie częściowo.
Dodatkowo oferuje obsługę pokrycia węzłów i gałęzi, które opcjonalnie można wykorzystać do sprawdzenia, czy są jakieś gałęzie nieujęte w testach.
Deep Cover jest prosty w użyciu i nie wymaga konfiguracji. Może być również zintegrowany z innymi narzędziami do analizy pokrycia kodu, takimi jak wbudowana biblioteka pokrycia kodu Ruby lub SimpleCov. W takich przypadkach, Deep Cover zaostrza analizę, oznaczając wiersze jako wykonane, tylko jeśli wszystko w danym wierszu kodu zostało w pełni wykonane.
Podsumowanie
Chociaż wysokie pokrycie kodu nie jest równoznaczne z brakiem błędów w oprogramowaniu, to jest to ważny wskaźnik, który należy brać pod uwagę podczas testowania. Pozwala ocenić, w jakim stopniu napisane testy rzeczywiście weryfikują kod źródłowy oprogramowania.
Dodatkowo, praca nad poprawą pokrycia kodu podczas testowania skutkuje powstaniem lepiej przetestowanego oprogramowania, które jest mniej podatne na błędy w środowisku produkcyjnym. Aby skutecznie analizować pokrycie kodu podczas testowania, warto rozważyć użycie jednego z narzędzi przedstawionych w tym artykule.
Warto również zapoznać się z narzędziami do testowania obciążenia opartymi na chmurze.