Programowanie w języku Delphi

Testy modułowe


Strona w budowie
Ktoś pracuje nad tą stroną, jej zawartość może się wkrótce zmienić. Prosimy o cierpliwość!





Rodzaje testów


W momencie, gdy program wymaga sprawdzenia funkcjonalności, należy przeprowadzić testy. Testy dzielimy na dwie główne grupy. Pierwsza z nich to testy "czarno-skrzynkowe" czyli testy funkcjonalne. Drugą grupę stanowią testy "biało-skrzynkowe", obejmujące testy jednostkowe, testy integracyjne i testy funkcjonalne.

Testy z pierwszej grupy zazwyczaj obejmują zagadnienia takie jak:
  • prawidłowe działanie interfejsu użytkownika,
  • prawidłowy przebieg wszystkich przypadków użycia,
  • prawidłowe działanie walidatorów.

Nazwę "czarno-skrzynkowe" zawdzięczają temu, iż testerzy nie wiedzą, jak system działa i co jest w środku. Zadaniem testerów jest sprawdzenie, czy program działa w prawidłowy sposób. Osoby testujące zazwyczaj nie uczestniczą w procesie wytwarzania oprogramowania.

Testy drugiej grupy obejmują sobą:
  • sprawdzenie prawidłowego współdziałania z platformą,
  • sprawdzenie prawidłowego współdziałania poszczególnych modułów,
  • sprawdzenie czy moduły dostarczają odpowiednich funkcjonalności w zamierzony sposób,
  • sprawdzenie prawidłowego działania poszczególnych klas i metod.

W poniższym artykule zajmiemy się ostatnią grupą testów.

Testy modułowe - Co i po co?


Testy modułowe (w ramach języka Java nazywane testami jednostkowymi) służą do sprawdzenia, czy metody testowanej klasy, funkcje lub procedury działają w zamierzony sposób. W języku Delphi najpopularniejszym mechanizmem prowadzenia testów modułowych jest wykorzystanie dołączenia sprawdzeń (tzw. inkluzji asercji) za pomocą procedury Assert. Procedura ta generuje wyjątek, gdy podana wartość logiczna, a więc sprawdzany warunek, nie jest prawdziwa. O ile, podczas pisania małych programów, wygodnym może okazać się umieszczenie wywołania tej procedury wewnątrz sprawdzanej funkcji, o tyle w dużych projektach zaleca się oddzielenie modułów testowania od samego programu.

Testowanie prostej funkcji


Prosty przykład sprawdzenia poprawności funkcji:
uses SysUtils;
 
//Funkcja testowana
function Kwadrat(x:double):double;
begin
result:=sqr(x);
end;
 
//Test
const Liczba = -1.234;
begin
Assert(Liczba*Liczba <> Kwadrat(Liczba));
end.


Biblioteka SysUtils zapewnia zaprezentowanie wyjątku, który może wystąpić w aplikacji, zamiast generowania Runtime Error. Jest ona niezbędna do organizacji testów modułowych.

Procedury testuje się trudniej, gdyż zamiast zwracanej wartości należy testować stan systemu (zawartości pamięci czy urządzeń) lub wartości parametrów podawanych inaczej niż przez wartość, a więc przez nazwę, przez wskaźnik czy przez zmienną globalną.

Testowanie z raportowaniem


Ponieważ procedura Assert generuje wyjątek w razie niezgodności, można wykorzystać bloki try do jego przechwycenia i ewentualnego wydrukowania informacji o niezgodności (na przykład na ekran lub do pliku). Wygodniejszym może jednak okazać się mechanizm, udostępniony przez sam język Delphi, a mianowicie zmienna globalna AssertErrorProc, przechowująca adres do procedury obsługi wyjątku asercji.

Przykład wykorzystania procedury obsługi niezgodności:
uses SysUtils;
 
//Funkcja testowana
function Kwadrat(x:double):double;
begin
result:=sqr(x);
end;
 
//Procedura obsługi niezgodności
procedure AssertErrorHandler(const Message, Filename: string; LineNumber: Integer; ErrorAddress: Pointer);
var TextFile:text;
begin
AssignFile(TextFile, 'c:\\Assert.log');
Rewrite(TextFile);
WriteLn(TextFile, Format('(Linia: %d, Adres: $%d) "%s": %s', [LineNumber, Integer(ErrorAddress), ExtractFileName(FileName), Message]));
CloseFile(TextFile);
end;
 
//Test
const Liczba = -1.234;
begin
AssertErrorProc:=AssertErrorHandler;
Assert(Liczba*Liczba <> Kwadrat(Liczba), 'Błąd funkcji Kwadrat(x);');
end.


Plik raportu w przypadku nieprawidłowego działania testowanej funkcji wyglądałby tak:
(Linia: 23, Adres: $4231552) "Project1.dpr": Błąd funkcji Kwadrat(x);


Jeśli wykorzystywana jest procedura obsługi niezgodności, procedura Assert nie generuje wyjątków.

Wersja testowa a wersja produkcyjna


TODO: Opisać dyrektywę $ASSERTIONS ON/OFF i dać przykład

Moduły testowe


TODO: Przedstawić przykład tworzenia modułu testowego do testowania klas podrzędnych

Moduły szkieletowe


TODO: Przedstawić przykład tworzenia modułu szkieletowego do testowania klas nadrzędnych