Code coverage – pokrycie kodu

Transkrypt

Code coverage – pokrycie kodu
Piotr Dwieczkowski
Code coverage
Mierzenie pokrycia kodu, teoria oraz praktyka w C/C++
Plan








Co to jest pokrycie kodu?
Możliwe sposoby wykorzystania
Rodzaje statystyk
Wady i zalety mierzenia porycia kodu
Narzędzia: gcov, lcov
Bardzo prosty przykład
Bardziej skomplikowane – CMAKE + gcov + lcov
Alternatywy
Co to jest pokrycie kodu?





Miara wykorzystywana przy testowaniu
oprogramowania
Opisuje w jakim stopieniu program został
sprawdzony przez testy
Zazwyczaj wykorzystywane przy określaniu
‘skuteczności’ testów jednostkowych
Dla większości języków istnieją zestawy narzędzi do
testowania/pomiaru pokrycia
Pokrycie możemy mierzyd według różnych kryteriów
Pokrycie linii kodu
ang. statement/line coverage
 Dla każdej linii kodu – czy instrukcje w danej linii
zostały uruchomione?
 Zależne od struktury tekstowej kodu, np. :
if( 1 == 0 ) printf(“hello world!”);
 Ta linia zawsze zostanie oznaczona jako uruchomiona
 Nie da nam to żadnej informacji o pokryciu printf
 Mało nam mówi o pętlach i instrukcjach warunkowcyh
Pokrycie funkcji
ang. function coverage
 Dla każdej funkcji – czy została wykonana?
 Pozwala szybko znaleźd funkcje, które nie są
przetestowane
 Lub np. nie są już używane
 Może byd przydatne przy prostym profilowaniu
 jeśli
zbieramy liczbę wywołao
 w tym wypadku najlepiej zbierad czas spędzony w
funkcji (gprof)
Pokrycie gałęzi
ang. branch/decision coverage
 Wymaga analizy struktury kodu
 Mierzy czy instrukcje warunkowe wykonały obie
ścieżki kodu (także pętle)
 Dokładniej – mierzy czy wartośd logiczna warunku
została wyliczona podczas uruchomienia jako
prawda i fałsz
 Nie bierze pod uwagę w jaki sposób została ona
wyliczona (ang. condition coverage)
Pokrycie ścieżek
ang. path coverage
 Mierzy pokrycie wszystkich możliwych ścieżek
wykonania funkcji
 Oczywiście pętle to utrudniają
 Możemy
wprowadzid dodatkowe kryteria
Zamiast nieskooczonej liczby ścieżek pętla dodaje dwie:
 Program nie
wszedł do pętli
 Program wszedł do pętli (i uruchomił ją dowolną liczbę razy)
Inne kryteria







Race coverage
Condition coverage (Multiple condition coverage)
Loop coverage
Data flow coverage
Relational operator coverage
Weak mutation coverage
…
Pokrycie kodu - wady, zalety
 Dobry sposób oceniania skuteczności testów
 Tworzenie testów dla pokrycia wymusza dodatkową
analizę kodu
 Dużo (raczej łatwych w obsłudze) narzędzi
 Nie istnieje idealna miara pokrycia
Nie można w 100% wierzyd, że wszystko zostało sprawdzone
 Wykonianie i analiza części z opisanych kryteriów może zająd
dużo czasu

 Z drugiej strony – nie zawsze opłaca się dążyd do 100%
pokrycia

Prawo malejących przychodów (ang. dimnishing returns)
gcov




Pozwala analizowad pokrycie linii kodu,
wykonywanych funkcji oraz gałęzi
Wchodzi w skład pakietu gcc, działa tylko z
programami skompilowanymi przez gcc (wymaga
specjalnych flag)
Dla podanego pliku źródłowego nazwa.cpp
generuje tekstowy plik nazwa.cpp.gcov zawierający
informacje o pokryciu dla każdej linii
Jest raczej nieprzyjemny w obsłudze – trudno go
ręcznie używad przy nieco większych projektach
Pliki .gcov
(wygenerowane przez gcov –b)
-:
0:Source:tmp.c
-:
0:Graph:tmp.gcno
-:
0:Data:tmp.gcda
-:
0:Runs:1
-:
0:Programs:1
-:
1:#include <stdio.h>
-:
2:
-:
3:int main (void)
function main called 1 returned 1
blocks executed 75%
1:
4:{
1:
5: int i, total;
-:
6:
1:
7: total = 0;
-:
8:
11: 9: for (i = 0; i < 10; i++)
branch 0 taken 91% (fallthrough)
branch 1 taken 9%
10: 10:
total += i;
-:
11:
1:
12: if (total != 45)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####:13:
printf ("Failure\n");
call
0 never executed
-:
14: else
1:
15:
printf ("Success\n");
call
0 called 1 returned 100%
1:
16: return 0;
-:
17:}
Jak to działa?

Podczas kompilacji podajemy do gcc odpowiednie flagi:
–fprofile–arcs –ftest–coverage

Gcc generuje pliki .gcno dla każdego pliku źródłowego


Oprócz tego do programu jest dołączany kod, który sprawia, że:



Zawierają one informacje o strukturze kodu
Podczas działania zbierane są statystyki pokrycia
Przed zakooczeniem programu dane są zapisywane w plikach .gcda (w
tym katalogu, w którym jest plik .gcno)
Każdemu plikowi źródłowemu odpowiada po jednym .gcda i .gcno
(ale nie plikom nagłówkowym)


Pomimo tego przy uruchomieniu gcov generuje pokrycie dla plików
nagłówkowych
Pliki .gcda i .gcno są binarne i są wykorzystywane przez np. gcov, gprof i
inne programy z gcc
Problemy



Nie możemy ustalid gdzie gcc zapisuje plik .gcno i
.gcda (zapisuje tam gdzie plik wyjściowy)
gcov musi zostad uruchomiony z tego samego
katalogu co gcc podczas kompilacji
Można podpowiedzied gdzie gcov ma szukad plików
lcov





Front-end do gcov
Pozwala na generowanie stron html z informacjami o
pokryciu dla poszczególnych plików
Dużo łatwiejszy w obsłudze – wystarczy podad katalog,
a lcov znajdzie pliki .gcda i .gcno (także w
podkatalogach) i dla każdego pliku źródłowego
przeanalizuje pokrycie
lcov zapisuje pokrycie dla całego katalogu w
pojedynczym pliku tracefile.info
genhtml zamienia plik .info w pliki html
lcov – możliwości




W jednym pliku .info mogą byd przechowywane
informacje o różnych uruchomieniach
Można przeglądad pokrycie według oddzielnie
uruchomionych testów
lcov umożliwia np. porównywanie uruchomieo
dodatkowo: lcov został stworzony w celu analizy
pokrycia kodu uruchomionego jądra Linux (w czasie
rzeczywistym)
gcov+lcov - tutorial

Kompilacja z flagami gcc/g++
g++ –fprofile–arcs –ftest–coverage main.cpp –o main


Zauważ utworzone pliki .gcno
Uruchom program tak jak zwykle
./main


Zauważ pliki .gcds
Jeśli używasz bezpośrednio gcov


gcov plik_zrodlowy.cpp (albo *.cpp)
Dla każdego pliku źródłowego otrzymujemy plik .cpp.gcov
Jeśli używasz lcov


uruchom lcov (najlepiej w oddzielnym katalogu) i wygeneruj html
mkdir report
cd report
lcov --capture --directory ../ --output-file main.info
c++filt < main.info > main.info (czytelne nazwy np. funkcji)
genhtml main.info
Otwórz index.html w ulubionej przeglądarce
Złożony przykład – CMAKE
 Należy
dodad flagi kompilatora – CMAKE tego nie
ułatwia (ze względu na przenośnośd)
 Mamy zmienną CMAKE_CXX_COMPILER_FLAGS
 Możemy ją
zmieniad w zależności od wartości opcji
 Wystarczy zrobid to raz dla całego projektu (zmienid flagi
przed dodawaniem podfolderów)
 Wykonujemy
make bez pokrycia, potem z pokryciem
 Nic się nie dzieje – CMAKE nie wie, że gcc powinien
wygenerowad pliki .gcno – nie szuka ich i nie wie, że
należy przebudowad projekt
Złożony przykład – Testowanie


UnitTest++ – wybrany na podstawie analizy dyskusji na
SO i kilku artykułów w sieci
 W łatwy sposób można tworzyd całe zestawy testów
Można też używad CTest
Może byd to zbyt duże narzędzie dla niewielkich projektów
 Nie zdążyłem przetestowad tego rozwiązania

Złożony przykład – Generowanie pokrycia

Próby dodania gcov jako TARGET w Makefile
żeby można było uruchomid make coverage
 taki TARGET można zdefiniowad jako obowiązkowy krok po
testach
 zarówno add_custom_target jak i add_custom_command
nie spełniają wszystkich wymagao
 trudno dostad się do plikó w.gcno
 powinny byd w katalogu CMakeFiles/target_name.dir/
 ale nie jest to zdefiniowane w żadnej stałej co oznacza, że
może się zmienid (znowu ze względu na przenośnośd)

Generowanie pokrycia – rozwiązanie


lcov służy właśnie do tego (i np. omija generację
plików .gcov)
Innym rozwiązaniem może byd CTest (w
dokumentacji jest wspomniana opcja generowania
pokrycia)
Alternatywy

Działające z gcc:
 ggcov
 Trucov
 gcc

pod cygwin
Visual Studio 2008/10
 Testowanie/pokrycie wbudowane


wersji
Linux/Windows – BullseyeCoverage
CTC++ TestCoverage
Urządzenia wbudowane



Jest to możliwe, ale nie ma dużo materiałów
O gcov+arm jest trochę informacji na grupach
dyskusyjnych
Jest też praca “Gcov on an embedded systems
 Skupia
się na architekturze PowerPC
Pytania?
Źródła

gcov



lcov


http://www.verifysoft.com/en_ctcpp.html
Różne rodzaje pokrycia z przykładami



http://www.bullseye.com/
CTC++ TestCoverage


http://code.google.com/p/trucov/
BullseyeCoverage


http://ltp.sourceforge.net/coverage/lcov.php
Trucov


man gcov
http://gcc.gnu.org/onlinedocs/gcc/Gcov.html
http://www.javaranch.com/journal/2004/01/IntroToCodeCoverage.html
http://www.bullseye.com/coverage.html
Gcov on an embedded system (H.Blasum, F.Görgen, J.Urban)

http://sysrun.haifa.il.ibm.com/hrl/greps2007/papers/gcov-on-an-embedded-system.pdf

Podobne dokumenty