Home > IT, programowanie, projekt > Testy, testy, testy

Testy, testy, testy

Grudzień 12th, 2008

Marudzenia ciąg dalszy. Temat 2: testy.

Bolączką większości projektów IT jest testowanie. Zapewnienie dobrego przetestowania aplikacji nie jest tematem prostym. Niestety w wielu przypadkach jest lekceważone.

Na początku zastanówmy się jakie mamy rodzaje testów:

  • jednostkowe - mamy dany kawałek kodu, piszemy dla niego testy, wiedząc jak jest zaimplementowany
  • integracyjne - sprawdzamy, czy poszczególne moduły systemu współpracują ze sobą jak należy
  • systemowe - sprawdzamy, czy cały system działa jak należy
  • akceptacyjne - weryfikują, czy aplikacja robi to co robić miała
  • wydajnościowe - sprawdzające, jak wydajne są poszczególne elementy systemu (lub cały system)
  • przeciążeniowe - sprawdzające, jak system zachowa się przy znacznie większym obciążeniu niż planowane
  • obciążeniowe - sprawdzające, jak system zachowuje się przy wysokim, ciągłym obciążeniu

Jest co najmniej jedno wspólne zagadnienie dla wszystkich tych testów - scenariusz. Testowanie bez scenariuszy jest jak strzelanie na ślepo w ciemnym lesie w środku nocy - a nóż coś się uda upolować :-) Jakie scenariusze mogą wystąpić w poszczególnych przypadkach?

  • testy jednostkowe - bardzo ważne jest testowanie warunków brzegowych, nietypowych oraz kilku typowych. Np. jeśli mamy metodę wykonującą dzielenie, to do takich warunków może należeć dzielenie przez zero, przez bardzo dużą liczbę, przez mały ułamek bliski zeru, przez jeden, przez liczby ujemne i kilka innych kombinacji wymienionych warunków. Należy takie same zastosować zarówno dla dzielnej i dzielnika. Do tego oczywiście należy przetestować kilka przykładów warunków typowych.
  • testy integracyjne - poszczególne komponenty mogą komunikować się ze sobą na różne sposoby, RMI, HTTP, SOAP, przekazanie wartości lub referencji do obiektu, itp. itd. Należy przetestować tutaj różne wartości przekazane - poprawne i niepoprawne, np. null zamiast obiektu. Z kolei dla poprawnie sformułowanych komunikatów warto przetestować wartości nietypowe - np. jeśli mój moduł wywoła metodę dzielenia na module obliczeń i przekażę zero jako dzielnik, to czy moduł obliczeń zachowa się poprawnie i odpowiednio mi to zakomunikuje?
  • testy systemowe - załóżmy, że mamy aplikację śledzącą nasze miesięczne wydatki. Chcemy sprawdzić, czy zapamiętywane są wszystkie dane, jakie wprowadziliśmy. Interesuje nas też, czy dobrze obsługiwane są wszystkie wartości jakie wprowadzamy (bardzo wysokie, ułamkowe, zerowe, ujemne).
  • testy akceptacyjne - znamy wymagania jakie zostały postawione systemowi. Na podstawie tych wymagań, możemy przygotować scenariusze testowe. Jeśli wymaganie mówi "umożliwić dodanie wydatku do systemu" należy taki sprawdzić, czy można w systemie taki wydatek dodać.
  • testy wydajnościowe - bazując dalej na przykładzie naszej aplikacji do monitoringu wydatków (zakładając, że jest to aplikacja web'owa) sprawdzić powinniśmy jak szybko "ładują" się poszczególne strony: zestawienie dzienne, tygodniowe, miesięczne, roczne, dla małej ilości wydatków, dla dużej ilości wydatków. Sprawdzamy, czy poszczególne elementy systemu działają wystarczająco szybko. Należy tutaj oczywiście wziąć pod uwagę warunki brzegowe ponownie: jeśli użytkownik nie wpisał żadnych wydatków, raport wygeneruje się szybko. Jeśli miał ich bardzo dużo, generacja zajmie pewnie więcej czasu - ale czy zmieści się w wymaganym przedziale?
  • testy przeciążeniowe - jeśli zakładaliśmy aktywność dla naszego systemu na ok. 100 użytkowników online jednocześnie, to w testach przeciążeniowych powinniśmy zasymulować ruch znacznie większej ilości użytkowników. Ważne jest też, aby odzwierciedlało to w sensowny sposób normalne działanie. Jeśli test wykonamy symulując 1000 użytkowników bez wydatków, pewnie pójdzie gładko. Czy to znaczy, że system obsłuży 1000 użytkowników jednocześnie zawsze? Nie koniecznie. Być może nie poradzi sobie z 50 użytkownikami z dużą ilością wpisanych wydatków. Jeśli natomiast nasz system poradzi sobie z 1000 użytkowników z dużą ilością wydatków - możemy raczej spać spokojnie.
  • testy obciążeniowe - w tym wypadku musimy przygotować scenariusz, gdy z systemu korzysta zakładane maksimum użytkowników, przez dłuższy czas non-stop. Być może chwilowo zwiększone użycie pamięci, które pojawi się przy testach przeciążeniowych, nie jest problemem. Ale przy ciągłym użyciu systemu pamięci może nam ostatecznie zabraknąć.

Oczywiście to wszystko nie jest takie proste. Testowanie jest trudną i skomplikowaną dziedziną, wymaga też trochę doświadczenia. Warto natomiast przy okazji każdego napotkanego problemu/błędu w naszej aplikacji zastanowić się, czy dało się to wcześniej przetestować.

Większość z powyższych testów da się zautomatyzować (a wręcz należy to zrobić). Z testami nie należy czekać do zakończenia projektów - zauważcie, że testy jednostkowe można zacząć przygotowywać już na samym początku (a metodologia Test Driven Development wręcz nakazuje rozpoczęcie pracy od przygotowania testów jednostkowych).

Ciekawym aspektem powyższego zestawu testów jest to, że pierwsze 4 testy są silnie od siebie zależne. Jeśli testy jednostkowe są dobrze wykonane, to jest większa szansa na wystąpienie mniejszej ilości błędów w kolejnych testach - i podobnie z następnymi. Poprawne wykonanie testów na poszczególnych etapach (a także zaimplementowanie aplikacji tak, aby dawała pozytywne rezultaty testów) zapewnia nam lepszą jakość i lepsze rezultaty przed wykonaniem kolejnego etapu.

Dla pozostałych rodzajów testów sprawa ma się podobnie: jeśli poszczególne elementy systemu są wydajne (w sensie użycia CPU, pamięci, szybkości działania), prawdopodobnie testy przeciążeniowe się powiodą i jest duża szansa, że również testy obciążeniowe również wypadną pomyślnie.

A jak to się dzieje, że testy i tak czegoś zazwyczaj nie wykażą? Wydaje mi się, że głównymi przyczynami jest komunikacja i niewiedza. Osoby wykonujące poszczególne testy powinny komunikować się między sobą. Programista piszący testy jednostkowe może zasugerować osobie wykonującej testy systemowe wprowadzanie nietypowych wartości. Osoba wykonująca testy akceptacyjne może zasugerować programiście "dodam do systemu duży plik PDF" - może programiście zaświeci się lampka "czy ten moduł do plików, który zrobiłem obsługuje duże pliki PDF?".

Inną sprawą jest niewiedza:

  • programiści nie do końca rozumieją, co implementują
  • testerzy nie do końca rozumieją, co testują
  • klient nie do końca rozumie to co wymaga i nie rozumie ograniczeń technicznych

Oczywiście nie zawsze ta niewiedza zachodzi ;-) Ale zazwyczaj wystarczająco często ;-)

Do poczytania:

Jakie są Wasze doświadczenia i opinie?

IT, programowanie, projekt

  1. No comments yet.
  1. No trackbacks yet.