INŻYNIERIA OROGRAMOWANIA TESTOWANIE JEDNOSTKOWE 2015/2016
Czemu testowanie jest ważne? 1994 gra Król Lew Błąd Excela 2007 (ile to jest 850*77,1?) 1987 Therac-25 (race condition, dokumentacja) i Cobalt60 (początek XX w) 1962 Sonda Mariner I samozniszczenie w 294 s ( najdroższy łącznik w historii ) zagrożenie bezpieczeństwa cywilnego 1998 Sonda Mars Climate Orbiter (różne systemy metryczne w różnych zespołach programistów) koszt 125 mln $ 1996 Rakieta Ariane 5 (błąd konwersji liczby 64-bitowej na 16 bitową) Procedura samozniszczenia po 39 s, koszt 500 mln $
Cele testowania (wg sylabusa ISTQB) Znajdowanie usterek Nabieranie zaufania do poziomu jakości Dostarczanie informacji do podejmowania decyzji (liczba błędów, odsetek pokrytych wymagań) Zapobieganie defektom (przez sam fakt projektowania testów)
Podstawowe pojęcia Obiekt testowany wyizolowana instancja klasy, która podlega testom Przypadek testowy weryfikacja poprawności konkretnego (pojedynczego) zachowania 1 metody w określonych warunkach. Dla każdej metody istnieje 1 lub więcej przypadków testowych, po jednym dla każdego rodzaju zachowania metody. Klasa testująca klasa z przypadkami testowymi dotyczącymi jednego obiektu testowanego
Testowanie to proces uruchamiania oprogramowania i jego obserwacji w poszukiwaniu błędów, nie zaś proces sprawdzania jego poprawności, gdyż nie jest to możliwe. Dlaczego? Zbyt wiele wartości parametrów wejściowych (poprawnych i niepoprawnych) Zbyt wiele możliwości przejścia przez kod Trudno oczekiwać sprawdzenia poprawności każdego programu lub złożonych interfejsów TESTOWANIE MA NA CELU ZNALEZIENIE JAK NAJWIĘKSZEJ LICZBY BŁEDÓW I PÓŹNIEJSZE ICH USUNIĘCIE
Biała skrzynka Potrzebna kompletna wiedza nt. budowy kodu Instrukcje warunkowe: a==b (2 testy) a>b (3 testy) instrukcje złożone dużo Zagnieżdżenia w pętlach mogą powodować lawinowy wzrost liczby przypadków testowych Pętle uruchomienie 0-krotne, 1-krotne, max-krotne Ogromna liczba możliwości powoduje że nie można tych testów przeprowadzić w całości Najłatwiejsze do wykonania w trakcie implementacji Linia kodu jest pokryta testem wówczas, gdy istnieje test którego działanie powoduje jej wykonanie. Zautomatyzowane środowiska testujące i raportujące pokrycie kodu: Rozbudowane typu Clover Proste (Coverlipse, plugin do Eclipse).
Czarna skrzynka Poszukiwanie: nieprawidłowych lub brakujących funkcji, błędów interfejsu, błędów w strukturach danych lub dostępie do zewnętrznych zasobów błędów wymagań funkcjonalnych i niefunkcjonalnych (efektywność), błędów inicjalizacji i finalizacji działania programu
Test jednostkowy (modułowy, komponentowy, podstawowy, programisty) Krótki program (fragment kodu) sprawdzający poprawność działania pojedynczych elementów programu (metod, obiektów). Metoda stosowana zarówno w programowaniu obiektowym jak i proceduralnym Testowanie jednostkowe odbywa się na bardzo niskim poziomie: pojedynczych klas i metod wywoływanych w określonym kontekście i z zadanymi parametrami. Przedmiotem testu jest wykonanie fragmentu kodu, a następnie porównanie rezultatów (stan, wynik liczbowy, zwrócony wyjątek ) z wynikami oczekiwanymi, także negatywnymi (niepowodzenie w działaniu oprogramowania również podlega testowaniu).
WAŻNE! TESTY JEDNOSTKOWE WYKONUJE PROGRAMISTA LUB TESTER JEDNOSTKOWY NIE JEST URUCHAMIANY CAŁY SYSTEM (PROGRAM) A JEDYNIE WYBRANY OBIEKT/METODA Przypadki testowe dotyczące jednego obiektu testowanego są zebrane wewnątrz jednej klasy testującej: 1klasa testowana = 1 klasa testująca
Analiza ścieżek Określany jest punkt początkowy oraz punkt końcowy dla przeprowadzenia testów, a następnie badany jest przebieg możliwych ścieżek pomiędzy nimi. Istnieją dwie opcje: każda możliwa ścieżka w każdej funkcji została przetestowana ścieżki są niemożliwe do sprawdzenia z powodu istnienia pętli, wówczas stosowane są 2 grupy testów: Boundary test działania w pętli nie są wykonywane lub działania w każdej pętli są wykonywane raz dodatkowo wszystkie ścieżki wewnątrz pętli są raz wykonane (zwracana wartość 0 lub 1 przejście). Interior test działania we wnętrzu pętli uważa się za przetestowane, jeśli zostały wykonane wszystkie ścieżki, które są możliwe przy dwukrotnym powtórzeniu pętli (zwracana wartość- 2 przejścia).
Klasy równoważności Jest to zbiór danych o podobnym sposobie przetwarzania, używanych do przeprowadzenia testu. Wykonanie testu z użyciem kilku elementów zbioru, powoduje uznanie całej klasy za poprawną i zwalnia nas od testowania wszystkich elementów w np. 1000-elementowym zbiorze.
Testowanie wartości brzegowych Rozwinięciem testów z użyciem klas równoważności jest testowanie wartości brzegowych. Wartość brzegowa to wartość znajdująca się wewnątrz, pomiędzy lub tuż przy granicy danej klasy równoważności.
Testowanie składniowe Polega na sprawdzeniu poprawności wprowadzanych danych do systemu: wymuszone wartości pól (bazy danych) autokorekty (MS Office) Zasada "garbage in garbage out brak mechanizmu walidacji danych na wejściu brak testów na tolerancje systemu na błędne dane
Testowanie mutacyjne Technika automatycznego badania, na ile dokładnie testy jednostkowe sprawdzają kod programu. Polega na automatycznym wielokrotnym wprowadzaniu małych losowych błędów w programie i uruchamianiu za każdym razem testów jednostkowych, które powinny te błędy wykryć. Testowanie mutacyjne wymaga dużej mocy obliczeniowej
TESTOWANIE METOD PRYWATNYCH (?)
W większości przypadków, klasę powinno się dać przetestować poprzez wywołanie jej metod publicznych. Jeżeli za prywatną lub chronioną metodą kryje się duża funkcjonalność, to być może jest to sygnał ostrzegawczy, który mówi ci, że w rzeczywistości ukryta jest tam odrębna klasa, która chciałaby wydostać się na zewnątrz /Thomas D. Hunt A, Pragmatic Unit Testing /
Czy to jest dopuszczalne? TAK. 1. Testuj wszystko, co może nie działać 2. Przetestowanie kodu jest ważniejsze niż zgodność z konwencją programowania obiektowego 3. Co jest ważniejsze: testy czy enkapsulacja?
Czy to jest dopuszczalne? I NIE. 1. Chęć testowania metod prywatnych jest próbą rozwiązania problemu z designem klasy, a więc ucieczką od problemu 2. Jeżeli coś jest zbyt trudne do przetestowania, prawdopodobnie jest to kwestia złej implementacji (code smell) 3. Przy programowaniu obiektowym nie powinno się zaglądać w szczegóły implementacyjne klasy 4. Metody prywatne są dużo częściej zmieniane niż publiczne, stąd ich testy są niemiarodajne 5. Podejście code first a podejście test first 6. Testując metody prywatne narażamy się na testowanie implementacji co przy zmianie kodu może wymusić zmianę testów.
TDD Testowanie całego kodu jedynie przez wywołanie metod interfesju, metody prywatne są wynikiem refaktoryzacji metod istniejących, dlatego też traktuje się je jako już przetestowane: Przykład: 1. Napisanie testu metody A 2. Napisanie metody A 3. REFAKTORYZACJA 4. Napisanie testu metody B 5. Napisanie metody B 6. REFAKTORYZACJA. Jeżeli metoda A i B mają część wspólną należy ją wyłączyć (extract method) w postaci (prywatnej) metody C. Skoro metoda C została wyodrębniona z 2 klas publicznych a więc przetestowanych, to traktuje się ją jako przetestowaną (pomimo jej prywatnego charakteru)
Jak testować metody prywatne? METODA 1. REFLEKSJA Zmiana modyfikatora dostępu (tylko na czas testów). Zaletą jest brak jakichkolwiek zmian w kodzie, wadą jest utrudniony refaktoring. Przykład z JUnit-addons (dodatek do JUnit)
Jak testować metody prywatne? METODA 1. DOMYŚLNY MODYFIKATOR DOSTĘPU Pozwala na dostęp do klasy tylko klasom z tego samego pakietu. Wystarczy, że testy są w tym samym pakiecie co klasa testowana, by po zmianie modyfikatora metod prywatnych na domyślne, mogły być one w ramach tego pakietu testowane. Wada: konieczność modyfikacji kodu źródłowego i dość znaczące odsłonięcie szczegółów implementacji klasy
Przykład: publizize.exe w VisualStudio class Klasa1 { private int PrywatneA; private int PrywatneBB; private event EventHandler Zdarzenie; } Uruchamiamy Visual Studio Command Prompt i wpisujemy: publicize.exe NazwaBiblioteki.dll W wygenerowanej bibliotece prywatne pola (PrywatneA, PrywatneB) będą dostępne jako publiczne. Wygenerowana biblioteka (NazwaBiblioteki_Accessor.dll) nazywana jest Private Accessor. Po podłączeniu do projektu, możemy przekonać się, że prywatne pola zostały zastąpione publicznymi: ClassLibrary1.Klasa_Accessor klasa; klasa.prywatnea = 3; klasa.prywatneb = 6;
Metody niepolecane (ale skuteczne) METODA 3 ASPECTJ czyli ARMATA NA WRÓBLE (niepolecane) Technologia jak i idea programowania aspektowego jest słabo znana i rozpowszechniona, stąd problemy w poprawianiu testów w nim pisanych przez następców METODA 4 (niepolecana) Umieszczenie kodu testującego w wewnętrznej klasie statycznej (wewnątrz klasy testowanej). Będzie miała ona dostęp do metod prywatnych, ale nastąpi wymieszanie kodu z testami, testy wejdą w skład programu wynikowego. KOD TESTUJĄCY W TEJ SAMEJ KLASIE CO KOD TESTOWANY METODA 5 Zadeklarować metodę jako protected i dziedziczyć w innej klasie która obuduje metodę prywatną metodą publiczną (Wrapper)