Testowanie i walidacja oprogramowania Inżynieria oprogramowania, sem.5 cz. 5 Rok akademicki 2010/2011 Dr inż. Wojciech Koziński Przykład Obliczmy sumę: 0+1+2+...+i, i є [0,100] read(i); if((i < 0)(i > 100)) error(); else {sum = 0; x = 0; while (x < i) { x = x + 1; if ( i == 10) sum = 1; else sum = sum + x;} print (sum) } TIWO cz. 5 2010/2011 2 Przykład test czar-skrzynkowy Kod programu jest niedostępny!! i = -1 i = 0 i = 1 i = 50 i = 99 i = 100 i = 101 jednakże i = 10 => AWARIA (sum = 1) TIWO cz. 5 2010/2011 3 1
Pojęcia podstawowe (1) Analizowane są szczegóły kodu źródłowego, Projekty testów bazują na strukturze kodu. Ścieżka wykonania: określona sekwencja instrukcji programu, która jest wykonywana przy określonym zestawie danych wejściowych (przypadek testowy), Dla różnych przypadków testowych => różne ścieżki wykonań, Testowanie grafu przepływu instrukcji (ang. control-flow testing): bazuje na kolejści wykonania instrukcji, Testowanie grafu przepływu danych (ang. data-flow testing): bazuje na kolejści operacji na wybranych danych. TIWO cz. 5 2010/2011 4 Pojęcia podstawowe (2) Graf przepływu (instrukcji): abstrakcyjne pojęcie przepływu w formie graficznej. Graf przepływu (danych): abstrakcyjne pojęcie przepływu danych, dla wybranych zmiennych w formie graficznej; rozszerzenie grafu przepływu instrukcji. Grafy przepływu instrukcji, grafy przepływu danych powinny być generowane automatycznie na podstawie kodu. Przypadki testowe projektowane są na podstawie grafów. Pokrycie (ang. coverage): względna liczba instrukcji (lub innych elementów grafu) wykonana podczas testowania, wyznaczana z grafu przepływu instrukcji lub danych. TIWO cz. 5 2010/2011 5 Struktury grafów przepływowych (1) s1 s2 lub s1; s2; p sn s1 s2 sn Sekwencja zdań s1; s2; ; sn Instrukcja warunkowa if (p) s1; else s2 TIWO cz. 5 2010/2011 6 2
Struktury grafów przepływowych (2) s p s p pętla (while do) while (p) do s pętla (do - while ) do s while (p) TIWO cz. 5 2010/2011 7 Struktury grafów przepływowych (3) s1 e1 s1 e2 p s e s2 s2 en sn pętla (for) for (s1: p: s2) do s przełącznik (switch - case) swich (e) {case e1:s1; case e2: s2; }; TIWO cz. 5 2010/2011 8 Testowanie przepływu instrukcji (1) Pokrycie: miara jak dobrze program (moduł) został przetestowany przez określony zbiór testów. Względna liczba węzłów (instrukcji) w grafie przepływów wykonana podczas testowania. Względna liczba krawędzi (przejścia do kolejnej instrukcji) w grafie przepływów wykonana podczas testowania. Pokrycie instrukcji: Każdy węzeł (instrukcja) powinien być wykonany przynajmniej jeden raz. Pokrycie gałęzi: Każda gałąź (przejście do kolejnej instrukcji) powinna być wykonana przynajmniej jeden raz. Różna siła skuteczści dla różnych definicji pokrycia. Specjalne procedury dla testowania pętli. TIWO cz. 5 2010/2011 9 3
Testowanie przepływu instrukcji (2) Ścieżka wykonania to sekwencja węzłów (i łączących je gałęzi) od jedynego węzła początkowego grafu do określonego węzła końcowego grafu. 4 1 2 5 3 6 7 8 TIWO cz. 5 2010/2011 10 Testowanie przepływu instrukcji (3) Zbiór P ścieżek wykonania spełnia kryterium pokrycia instrukcji, wtedy i tylko wtedy, gdy dla każdego węzła n w grafie przepływu instrukcji istnieje przynajmniej jedna ścieżka p w zbiorze P, która zawiera węzeł n. Inaczej: każda instrukcja w programie jest wykonana przynajmniej jeden raz w czasie testowania. Spełnione kryterium => 100% pokrycia instrukcji. Niespełnione kryterium => częściowe pokrycie (<100%). Węzeł początkowy, węzeł końcowy, złączenia są wyłączone z kryterium. Pełne pokrycie instrukcji jest trudne do osiągnięcia w praktyce ze względu na nie wykonywalny kod oraz kompilacje warunkowe. TIWO cz. 5 2010/2011 11 Testowanie przepływu instrukcji (4) Zbiór P ścieżek wykonania spełnia kryterium pokrycia gałęzi, wtedy i tylko wtedy, gdy dla każdej gałęzi e w grafie przepływu instrukcji istnieje przynajmniej jedna ścieżka p w zbiorze P, która zawiera gałąź e. Inaczej: każda gałąź / decyzja (prawda / fałsz, tak / nie) w programie jest wykonana przynajmniej jeden raz w czasie testowania. Spełnione kryterium => 100% pokrycia gałęzi. Całkowite pokrycie gałęzi => zapewnia całkowite pokrycie instrukcji. Zwykle jest konieczna większa liczba testów dla całkowitego pokrycia gałęzi niż całkowitego pokrycia instrukcji. Pokrycie gałęzi jest silniejszym testem niż pokrycie instrukcji. Niespełnione kryterium => częściowe pokrycie (<100%). TIWO cz. 5 2010/2011 12 4
Testowanie przepływu instrukcji (5) error() read(i) (i<0) (i>100) sum=0;x=0 i= -1 i= 0 i= 1 i= 50 i= 99 i= 100 i= 101 print(sum) x<i sum=1 x=x+1 i==10 sum=sum+x Pokrycie instrukcji 9 / 10 = 90% Pokrycie gałęzi 13 / 15 = 87% Nie wykona!!! TIWO cz. 5 2010/2011 13 Testowanie przepływu instrukcji (6) read(i) (i<0) i= -1 i= 1 i= 10 (i>100) error() sum=0;x=0 print(sum) x<i sum=1 x=x+1 i==10 sum=sum+x Pokrycie instrukcji 10 / 10 = 100% Pokrycie gałęzi 15 / 15 = 100% TIWO cz. 5 2010/2011 14 pokrycie instrukcji pokrycie gałęzi (1) Obliczmy sumę: 0+1+2+...+i, i є [0,100] read(i); if((i < 0)(i > 100)) error(); else {sum = 0; x = 0; while (x < i) { x = x + 1; if ( i <> 10) sum = sum + x;} // zmiana // if ( i == 10) sum = 1; else sum = sum + x;} print (sum) } TIWO cz. 5 2010/2011 15 5
pokrycie instrukcji pokrycie gałęzi (2) read(i) (i<0) (i>100) i= -1 i= 1 error() sum=0;x=0 print(sum) x<i x=x+1 i==10 sum=sum+x Pokrycie instrukcji 10 / 10 = 100% Pokrycie gałęzi 13 / 14 = 93% Nie wykonane!! TIWO cz. 5 2010/2011 16 pokrycie instrukcji pokrycie gałęzi (3) read(i) i= 10 error() (i<0) (i>100) sum=0;x=0 sum = 0 AWARIA!!! x<i x=x+1 print(sum) i==10 sum=sum+x Teraz wykona! TIWO cz. 5 2010/2011 17 Pokrycie warunkowe Zbiór P ścieżek wykonania spełnia kryterium pokrycia warunków, wtedy i tylko wtedy, gdy dla każdego warunku zawierającego predykaty (c 1, c 2,,c n ), c i przyjmuje wartość true () gdy znajduje się w ścieżce p j w zbiorze P oraz c i przyjmuje wartość false () gdy znajduje się w ścieżce p k w zbiorze P dla i,j,k = 1,2,,n. Wewnętrzna struktura predykatów musi być brana pod uwagę: (i<0)(i>100), {true / false} {true / false} Każdy predykat prosty (atomowy) musi być przetestowany oddzielnie. TIWO cz. 5 2010/2011 18 6
Pokrycie wielo-warunkowe Zbiór P ścieżek wykonania spełnia kryterium pokrycia wielo-warunkowego, wtedy i tylko wtedy, gdy dla każdego warunku zawierającego predykaty (c 1, c 2,,c n ), wszystkie możliwe kombinacje ich wartości są realizowane w jednej ze ścieżek p k w zbiorze P dla k = 1,2,,n. Wymaganie silniejsze niż pokrycie warunków. Dla 2 warunków atomowych 4 kombinacje, Dla 3 warunków atomowych 8 kombinacji. TIWO cz. 5 2010/2011 19 Pokrycie wszystkich ścieżek Każda możliwa ścieżka w programie zostanie wykonana. Jest to najsilniejsze kryterium. Zwykle jest nie możliwe do osiągnięcia. Kryterium słabsze - to pokrycie niezależnych ścieżek. Jest o silniejsze niż pokrycie gałęzi. TIWO cz. 5 2010/2011 20 Porównanie kryteriów (1) Kryterium pokrycia instrukcji Kryterium pokrycia gałęzi Kryterium pokrycia warunków Kryterium pokrycia wielo-warunkowego if ((x <> 0) && (z >= 0)) y = z/x (x <> 0) && (z >= 0) y = z/x TIWO cz. 5 2010/2011 21 7
Porównanie kryteriów (2) Pełne spełnienie kryterium pokrycia instrukcji: {x = 1, z = 0} [1 test], Pełne spełnienie kryterium pokrycia gałęzi: {x = 1, z = 0} dla gałęzi oraz {x = 1, z = -1} dla gałęzi. [2 testy], Pełne spełnienie kryterium warunków: {x = 0, z = 0} dla kombinacji (false, true) oraz {x = 1, z = -1} dla kombinacji (true, false). (gałąź jest nie przetestowana!) [2 testy], Pełne spełnienie kryterium wielo-warunkowości: {x = 1, z = 0} dla kombinacji (true, true), {x = 1, z = -1} dla kombinacji (true, false), {x = 0, z = 0} dla kombinacji (false, true), {x = 0, z = -1} dla kombinacji (false, false). [4 testy] TIWO cz. 5 2010/2011 22 Wybór przypadków testowych Dla wybranego kryterium pokrycia i żądanej wartości kryterium, należy zaprojektować przypadki testowe by spełnić zadane warunki. Zbudować graf badanego modułu (należy użyć narzędzia), Wybrać ścieżki, które spełniają kryterium, Dla każdej z wybranych ścieżek, zaprojektować przypadki testowe (wartości zmiennych wejściowych), które spowodują wykonanie odpowiedniej ścieżki. Wykonać test, z wykorzystaniem narzędzia, które oblicza pokrycie, Jeżeli żądana wartość pokrycia nie została osiągnięta, wówczas należy zaprojektować we przypadki testowe. Heurystyka: należy zacząć od końca ścieżki i posuwać się w górę tując napotkane warunki. Analiza tych warunków może prowadzić do wyboru właściwych wartości zmiennych wejściowych. TIWO cz. 5 2010/2011 23 Testowanie pętli (1) Pętle proste Pętle zagnieżdżone Pętle seryjne TIWO cz. 5 2010/2011 24 8
Testowanie pętli (2) Testowanie pętli prostych: 0 iteracji (pętla nie wykonana), minimalna liczba iteracji, minimalna+1 liczba iteracji, typowa liczba iteracji, maksymalna-1 liczba iteracji, maksymalna liczba iteracji, maksymalna+1 liczba iteracji (może być niemożliwe), Pętle z ustaloną liczba iteracji nie poddają się wszystkim sugerowanym testom przykładowo: for (j=0; j<999; j++) { }. Testowanie pętli seryjnych: Jeżeli nie ma przepływu danych między nimi, to należy testować osob jako pętle proste, Jeżeli występuje przepływ danych, to należy testować jako pętle zagnieżdżone (reguły będą później). Testowanie pętli nieustrukturyzowanych (ze skokami): zmienić kod na kod strukturalny. TIWO cz. 5 2010/2011 25 Testowanie pętli (3) Testowanie pętli zagnieżdżonych: możliwa bardzo duża liczba przypadków testowych więc: Pętla (najbardziej) wewnętrzna jest testowana jak pętla prosta, pętla zewnętrzne testowane są minimalna liczbą iteracji. Ustawienie pętli wewnętrznej by wykonywała typową liczbę iteracji. Przetestować pętlę nadrzędną wykorzystując strategie testowania pętli prostej. Pętle zewnętrzne wykonywane są minimalną liczbę razy. Powtarzać poprzednie dwa etapy, aż osiągnięta zostanie pętla zewnętrzna. Powtórzyć test z maksymalnymi liczbami iteracji dla wszystkich zagnieżdżonych pętli. TIWO cz. 5 2010/2011 26 Testowanie przepływu danych (1) Zdarzenia dotyczące poszczególnych zmiennych: d (defined): zmienna otrzymuje wartość za pomocą instrukcji przypisania, zainicjowania, instrukcji wejścia, k (killed): wartość zmiennej staje się nieokreślona (brak referencji, NaN), u (used) zmienna została użyta w: c (computation) obliczeniach, zwykle po prawej stronie, p (predicate) w warunku sterującym kolejścią wykonywania instrukcji. TIWO cz. 5 2010/2011 27 9
Testowanie przepływu danych (2) Przypadki przepływu danych: ;x:=1; y:=y+10; read(z); z:=x+y+z; d u dd: podejrzane, może być nieszkodliwe x:=1; x:=2; dk: prawdopodobnie błąd. Zmienna zdefiniowana lecz nie użyta. du: przypadek rmalny, zmienna zdefiniowana i użyta, kd: przypadek rmalny, zmienna zniszczona i pownie zdefiniowana, kk: przypadek nieszkodliwy, lecz pewnie błędny po co niszczyć zmienna dwa razy? ku: błąd. Zmienna zniszczona nie może być użyta. TIWO cz. 5 2010/2011 28 Testowanie przepływu danych (3) ud: przypadek rmalny y:=x+1; x:=x+1; uk: przypadek rmalny, uu: przypadek rmalny y:=x+x; -d: przypadek rmalny, -k: prawdopodobnie błąd, zmienna niszczona lecz nie była wcześniej użyta, -u: prawdopodobnie błąd, zmienna użyta bez nadania jej wartości, d-: podejrzane, po co definiować zmienną, która nie została użyta, k-: przypadek rmalny, u-: przypadek rmalny, jednakże dla zmiennych dynamicznych, powinna być zwolniona pamięć. TIWO cz. 5 2010/2011 29 Testowanie przepływu danych (4) Metody testowania Zbudowanie grafu przepływu danych z adtacjami dotyczącymi wybranej zmiennej, Adtacje, umieszczenie przy każdym węźle symboli d, k, c, p, u. Różne sposoby oceny pokrycia, jak sekwencje d, k, c, p, u są wykonywane podczas przebiegów testowych. Testy przepływu danych są silniejsze niż testy przepływów. TIWO cz. 5 2010/2011 30 10
Testowanie przepływu danych (4) Ścieżka bez definicji ze względu na zmienną x, to ścieżka w której nie występuje operacja (d) definiowania wartości zmiennej. Definicja (d) wartości zmiennej x w węźle n osiąga węzeł v z użyciem tej zmiennej (u, c, p), wtedy i tylko wtedy, gdy istnieje ścieżka przez węzły (n,w 1,w 2,,w m,v) od n do v nie zawierająca definicji zmiennej x. = x x = x = x = x d u(p) u(c) u(c) TIWO cz. 5 2010/2011 31 Kryteria przepływu danych (4) Zbiór ścieżek P spełnia kryterium wszystkich definicji (ang. all-definitions criterion) (ze względu na zmienną x), wtedy i tylko wtedy, gdy dla każdej definicji (d) zmiennej x, istnieje przynajmniej jedna ścieżka w zbiorze P, która dociera do użycia (u, c, p) zmiennej x. Zbiór ścieżek P spełnia kryterium wszystkich zastosowań (ang. all-uses criterion) (ze względu na zmienną x), wtedy i tylko wtedy, gdy dla każdej definicji (d) zmiennej x i dla wszystkich użyć zmiennej x, istnieje przynajmniej jedna ścieżka w zbiorze P, która dociera do użycia (u, c, p) zmiennej x wychodząc z definicji d. TIWO cz. 5 2010/2011 32 Przykład (1) Obliczmy sumę: 0+1+2+...+i, i є [0,100] read(i); if((i < 0)(i > 100)) error(); else {sum = 0; x = 0; while (x < i) { x = x + 1; if ( (i==1)(i == 10)) sum = 1; else sum = sum + x;} print (sum) } Wybra zmienną sum do analizy. TIWO cz. 5 2010/2011 33 11
Przykład (2) read(i) (i<0) (i>100) d error() sum=0;x=0 x<i c print(sum) d x=x+1 (i==1) (i==10) cd i= 1 i= 2. 100% pokrycia dla kryterium wszystkich zastosowań sum=1 sum=sum+x TIWO cz. 5 2010/2011 34 Przykład (3) read(i) (i<0) (i>100) d error() sum=0;x=0 x<i c print(sum) d sum=1 x=x+1 (i==1) (i==10) sum=sum+x cd i= 1 i= 2. <100% pokrycia dla kryterium wszystkich zastosowań (użyć) i = 0 TIWO cz. 5 2010/2011 35 Porównanie testów biało- i czar-skrzynkowych Testy biało-skrzynkowe Potencjalnie nieskończenie wielka liczba testów do otrzymania zadowalającego pokrycia, Testowanie tego co zostało napisane, a nie tego co miało być napisane, Nie wykrywa brakujących funkcjonalści. Testy czar-skrzynkowe Kombinatoryczny wybuch liczby testów, Czasem nieczytelna (trudna) diagstyka usterki, Brak możliwości wykrycia dodatkowych ukrytych funkcjonalści. Oba rodzaje testów są niezbędne, Stawią one ekstrema sposobów testowania. Wybór sposobów testowania zależy od: Liczby możliwych, logicznych ścieżek wykonań, Rodzaju danych, Mocy obliczeniowej, Rodzaju i stopnia skomplikowania algorytmów i struktur danych TIWO cz. 5 2010/2011 36 12