e-Informatica Software Engineering Journal Język opisu przypadków testowych ukierunkowany na Rational Robota

Język opisu przypadków testowych ukierunkowany na Rational Robota

Maciej Gabor,  Jerzy Nawrocki
Instytut Informatyki,  Politechnika Poznańska
mgabor@bestcom.com.pl  Jerzy.Nawrocki@put.poznan.pl

Jeżeli chcemy, by programiści i klienci pisali testy, musimy uczynić ten proces jak najmniej bolesnym.

–K. Beck
Streszczenie

Metodyka Programowania Ekstremalnego kładzie szczególny nacisk na automatyczne testowanie jako sposób zapewniania jakości. Testy akceptacyjne (akcje użytkownika, dane wejściowe, spodziewane wyniki) projektowane są przez klienta, a liczbę pozytywnie wykonanych testów traktuje się jako miarę postępu prac. W rozdziale zaproponowano język skryptowy pozwalający zwięźle opisywać testy akceptacyjne dla aplikacji internetowych. Wykonanie tych testów dzięki stworzonemu kompilatorowi odbywa się w środowisku Rational Robot. Przedstawione podejście pozwala opisywać przypadki testowe przed implementacją testowanej cechy systemu.

1. Wstęp#

Nieadekwatne testowanie oprogramowania kosztuje rocznie gospodarkę Stanów Zjednoczonych 59,5 miliarda dolarów, tj. około 0,6 procenta PKB tego kraju. Szacuje się, że możliwe do osiągnięcia ulepszenia infrastruktury testowania mogłyby ograniczyć ten koszt o ponad 22 miliardy [NIST2002]. Gwałtowny i wręcz agresywny rozwój oprogramowania, jaki obserwujemy w ostatnich latach, domaga się radykalnych wysiłków w zakresie jego testowania [JEFF1999]. Wysiłki te powinny obejmować między innymi ulepszanie procesów, standaryzację, stosowanie tzw. dobrych praktyk oraz wprowadzanie nowoczesnych narzędzi.W ostatnich latach pojawiło się wiele interesujących narzędzi wspomagających rozwój i pielęgnację oprogramowania. Ich twórcy poświęcili wiele uwagi problemom testowania. Wśród narzędzi komercyjnych ciekawą propozycją jest pakiet Rational Suite. Narzędzia wchodzące w jego skład wspomagają między innymi: zarządzanie wymaganiami (RequisitePro), modelowanie i projektowanie wizualne (Rose), automatyczne testowanie funkcjonalne i wydajnościowe, testy obciążeniowe (TestManager, TestFactory, Robot, Quantify, PureCoverage), śledzenie procesu usuwania defektów (ClearQuest), zarządzanie konfiguracją (ClearCase LT), zaawansowane raportowanie (SoDA), planowanie (ProjectConsole, TestManager). Zaletami pakietu Rational Suite jest jego kompletność i eleganckie zintegrowanie narzędzi. Dodatkowym atutem jest Rational Unified Process (RUP) – zestaw dobrych praktyk, wskazówek i instrukcji dla każdej fazy cyklu życia oprogramowania. Wszystko to przesądza o silnej pozycji pakietu na rynku.

W latach 90-tych dojrzały również metody testowania. Pojawiły się takie metodyki, jak Programowanie Ekstremalne (w skrócie XP od ang. eXtreme Programming), w których testowanie odgrywa kluczową rolę. Kent Beck, jeden z głównych twórców XP, twierdzi wręcz, że „właściwości oprogramowania, których nie można sprawdzić przez automatyczne testy, po prostu nie istnieją” [BECK2001]. W XP kładzie się szczególny nacisk na automatyczne testowanie jako sposób zapewniania jakości. Testy akceptacyjne tworzone są zawsze pod dyktando klienta. Ich implementacją zajmują się informatycy (reprezentant klienta nie zna najczęściej narzędzi testowania takich jak Rational Robot). W XP jako miarę postępu prac przyjmuje się liczbę pozytywnie wykonanych testów akceptacyjnych. Takie podejście wymaga istnienia języka skryptowego, przy pomocy którego można by zapisywać przypadki testowe. Skrypty przypadków testowych powinny być łatwe do zrozumienia i gotowe do wykonania jeszcze przed implementacją testowanej cechy systemu.

W pakiecie Rational Suite skrypty przypadków testowych zapisywane są w języku SQABasic. Niestety, język ten jest bardzo nieczytelny. Patrząc na skrypt przypadku testowego trudno jest stwierdzić, co jest właściwie przedmiotem testowania. Problem ten wynika z przyjętej koncepcji, zgodnie z którą dane dotyczące weryfikacji oddzielone są od skryptów testowych i schowane głęboko w katalogach systemu Rational Suite. Rozwiązanie takie praktycznie uniemożliwia pisanie przypadków testowych i skazuje programistów na korzystanie wyłącznie z techniki zapisu sesji i odtwarzania (ang. capture&play) oraz związane z tym niedogodności (przy intensywnym strumieniu zmian, co jest właściwe dla przedsięwzięć realizowanych zgodnie z XP, koszty pielęgnacji przypadków testowych stają się tak duże, że technika ta przestaje mieć sens ekonomiczny [GRAH1999]).

W rozdziale przedstawiono propozycję języka skryptowego WebTest służącego do opisu przypadków testowych. Jest on ukierunkowany na pakiet Rational Suite. Proponowany język pozwala w prosty i czytelny sposób opisywać testy akceptacyjne dla aplikacji internetowych. Dzięki opracowanemu kompilatorowi skrypty zapisane w języku WebTest wykonywane są przez Rational Robota. Krótki opis narzędzia Rational Robot i języka SQABasic wraz z przykładem testu akceptacyjnego został przedstawiony w podrozdziale 2. Język opisu przypadków testowych oraz przykład jego użycia zaproponowano w podrozdziale 3. Uwagi implementacyjne związane z budową kompilatora zamieszczone zostały w podrozdziale 4. Automatyczne testowanie wymaga porównywania dokumentów generowanych przez system (raporty, faktury itp.) z ich wartościami oczekiwanymi (wzorcowymi). Niekiedy dokumenty te zawierają elementy zmienne (np. datę), które przy kolejnym wykonaniu testu mogą mieć inne wartości. W podrozdziale 5. zaproponowano technikę maskowania elementów zmiennych wykorzystującą wzorce dokumentów. Uwagi implementacyjne dotyczące tej techniki przedstawiono w podrozdziale 6.

2. Testowanie aplikacji internetowych i Rational Robot#

Rational Robot [ROBO2001] jest narzędziem automatyzacji procesu testowania aplikacji typu klient/serwer oraz aplikacji internetowych działających pod kontrolą systemu Microsoft Windows (95, 98, NT 4.0, 2000). Robot pozwala tworzyć skrypty testowe na podstawie zapisu sesji (mechanizm capture&play). Polega to na uruchomieniu aplikacji, którą testujemy i pracy z nią. Wszystkie wykonane operacje Robot zapisuje w postaci skryptu języka SQABasic. Testowanie odbywa się zawsze poprzez interfejsy użytkownika, których elementy identyfikowane są głównie na podstawie nazw. W prosty sposób możemy konfrontować stan testowanej aplikacji z oczekiwaniami, osadzając w skryptach tzw. punkty weryfikacji. Punkt weryfikacji jest to miejsce w skrypcie testowym (np. wywołanie funkcji SQABasica), w którym porównuje się aktualne wyniki działania aplikacji (stan bazy danych, tekst wyświetlany na ekranie, przesyłane komunikaty itp.) z wartościami oczekiwanymi. Dla punktów weryfikacji można określić dodatkowe atrybuty, np. czas oczekiwania na przejście do pożądanego stanu. Dla aplikacji internetowych wykorzystuje się jedynie dwa typy punktów weryfikacji:

  • Object Data – sprawdza dane umieszczone w elementach stron WWW, np. zawartość pól edycyjnych, paragrafów, tabel, list wyboru, itp.
  • Object Properties – sprawdza wszystkie właściwości elementów stron WWW, np. typ, długość pola edycyjnego, aktywność, stan, wartość elementu, nazwę znacznika HTML, itd.

Rozważmy prostą aplikację internetową stworzoną dla przykładowego wydawnictwa. Wygląd tej aplikacji przedstawiony został na rysunku 1. Aplikacja umożliwia przesłanie na wskazany adres email informacji o pozycjach książkowych i cenach. W celu przesłania tych danych konieczne jest wypełnienie prostego formularza. Należy podać adres email, wybrać interesującą czytelnika kategorię oraz poziom zaawansowania a następnie przesłać formularz. W przypadku podania nieprawidłowego adresu email wyświetlony zostaje (poniżej formularza) stosowny komunikat.

Zaprezentowana na rysunku 1. strona WWW składa się z dwóch ramek (o nazwach: LEFT_FRAME i RIGHT_FRAME). Lewa ramka zawiera prosty formularz (nazwa: SIMPLE_FORM). Ramka prawa pozwala przejść do sklepu internetowego i innych stron zawierających informacje o wydawnictwie. Kolejnymi cyframi oznaczone zostały istotne elementy strony. Każdy z nich identyfikowany jest jednoznacznie przez nazwę:

  • pole edycyjne EDITBOX1 – 1
  • lista wielokrotnego wyboru LISTBOX1 – 2
  • lista rozwijalna COMBO1 – 3
  • pole opcji CHECKBOX1 – 4
  • przycisk SUBMIT1 – 5
  • paragraf PARAGRAPH1 – 6
  • hiperłącze LINK1 – 7
  • obraz IMAGE1wraz z obszarem aktywnym AREA1 – 8

fig1.png

Rys. 1. Przykładowa aplikacja internetowa

Rozważmy prosty test akceptacyjny. Reprezentant klienta opisuje krótki scenariusz użycia: w polu email wpisujemy nieprawidłowy adres: „mgabor@@z.pl”, wybieramy kategorię „Networks” i poziom „Intruductory” i naciskamy „Send”. Aplikacja powinna wyświetlić poniżej formularza informację o nieprawidłowym adresie email. Implementacja takiego przypadku testowego za pomocą Rational Robota jest bardzo prosta. W środowisku Robota rozpoczynamy zapis sesji. Uruchamiamy przeglądarkę internetową a w niej testowaną aplikację. Następnie wypełniamy odpowiednie pola i naciskamy „Send”. Ostatnią czynnością jest dodanie punktu weryfikacji. Wybieramy punkt weryfikacji typu Object Data i wskazujemy myszką paragraf oznaczony na rysunku 1. cyfrą . Rational Robot zapisze wszystkie czynności w postaci skryptu języka SQABasic:

Sub Main
    Dim Result As Integer
    'Initially Recorded: 2003-05-06  22:21:03
    'Script Name: atest
    StartBrowser "http://www.webtest.pl", "WindowTag=WEBBrowser1" 
    Window SetContext, "WindowTag=WEBBrowser1", ""
    Browser SetFrame,"Type=HTMLFrame;HTMLId=LEFT_FRAME",""
    Browser NewPage,"HTMLTitle=WebTest Publishing House",""
    EditBox Click, "Type=EditBox;Name=EDITBOX1", "Coords=59,10"
    InputKeys "mgabor@@z.pl"
    ListBox Click, "Type=ListBox;Name=LISTBOX1", "Text=Networks"
    ComboBox Click, "Type=ComboBox;Name=COMBO1", ""
    ComboListBox Click, "Type=ComboListBox;Name=COMBO1", 
    "Text=Introductory."
    PushButton Click, "Type=PushButton;Name=SUBMIT1"
    Browser SetFrame,"Type=HTMLFrame;HTMLId=LEFT_FRAME",""
    Browser NewPage,"HTMLTitle=WebTest Publishing House",""
    __Result = HTMLVP (CompareData, "Type=HTML;HTMLId=PARAGRAPH1", __
        __"VP=Object Data")__
End Sub

Niewątpliwą zaletą narzędzia Rational Robot jest łatwość zapisywania przypadków testowych (mechanizm capture&play). Nie jest tu konieczna znajomość języków programowania. Podejście to ma jednak dwie wady:

  • Do „nagrania” testu konieczne jest posiadanie gotowego interfejsu użytkownika testowanej aplikacji. Rational Robot jest więc szczególnie przydatny dla testowania regresyjnego. Nie nadaje się natomiast do tworzenia przypadków testowych przed kodowaniem (jest to jedna z istotnych praktyk Programowania Ekstremalnego [BECK2001])
  • Kod skryptów testowych w języku SQABasic nie jest czytelny. W skrypcie umieszczonym powyżej trudno jest odnaleźć wykonane operacje. Punkt weryfikacji widoczny jest jako wywołanie funkcji HTMLVP (druga i trzecia linia od końca skryptu zaznaczona pogrubioną czcionką). Nie widzimy jednak z jaką wartością porównywana jest zawartość paragrafu PARAGHRAPH1.

Ręczne zaimplementowanie rozważanego prostego przypadku testowego wymagałoby dobrej znajomości języka SQABasic oraz struktur wykorzystywanych przez Rational Robota do przechowywania danych dotyczących weryfikacji. Taki sposób implementacji jest ze względów praktycznych nie do przyjęcia.

3. Propozycja języka opisu przypadków testowych#

Rational Robot jest rozbudowanym narzędziem stanowiącym ciekawą propozycję dla osób zajmujących się testowaniem akceptacyjnym, szczególnie testowaniem aplikacji internetowych. Nie jest jednak praktycznie możliwe posiadanie gotowych do wykonania przypadków testowych przed zakończeniem implementacji testowanej cechy systemu. Pielęgnacja i utrzymanie testów (ang. maintenance), ze względu na niską czytelność skryptów testowych, jest czasochłonna i trudna. Poniżej zamieszczona została propozycja języka WebTest, który stanowić może rozwiązanie wspomnianych problemów. Przy projektowaniu tego języka położono szczególny nacisk na wysoką czytelność kodu i usprawnienia, pozwalające maksymalnie ułatwić pielęgnację przypadków testowych. Prezentowany język obejmuje trzy aspekty związane z ich opisem: strukturę strony WWW, akcje użytkownika i punkty weryfikacji.

3.1. Struktura strony WWW#

Łatwe implementowanie przypadków testowych wymaga określenia struktury stron WWW. Opis taki pozwala na zwięzłe odwoływanie się do elementów stron w opisanych dalej akcjach użytkownika i punktach weryfikacji. Opis struktury został wyraźnie oddzielony od pozostałych części. Podejście takie pozwala wielokrotnie korzystać z tych samych opisów bez duplikacji kodu. Brak takiej duplikacji jest szczególnie ważny przy pielęgnacji kodu [FOWL1999, PIPK2002]. Konieczne zmiany wystarczy wprowadzić w jednym opisie struktury, który może być wykorzystywany w wielu przypadkach testowych.Proponowany język WebTest pozwala na czytelne zapisanie hierarchicznej budowy stron WWW. Strona WWW składa się z ramek (ang. frames). Ramki zawierają paragrafy, tabele, grafikę, powiązania do innych stron (ang. hyperlink) oraz formularze. Formularze mogą zawierać wyżej wymienione elementy a ponadto pola edycyjne (ang. editbox, textarea), listy wielokrotnego wyboru (ang. listbox), listy rozwijalne (ang. combobox), przyciski, pola opcji (ang. checkbox), przyciski typu radio (ang. radiobox). Tabele mogą zawierać wszystkie wyżej wymienione elementy prócz ramek. Grafika może posiadać kilka tzw. obszarów aktywnych (ang. area, areamap). Struktura jest więc rekurencyjna. Elementy powinny być zawsze jednoznacznie identyfikowalne. Poniżej przedstawiony został skrypt języka WebTest opisujący strukturę strony WWW aplikacji opisanej w podrozdziale 2. i pokazanej na rysunku 1.

frames {
    LEFT_FRAME
    RIGHT_FRAME
}
LEFT_FRAME {
    form FORM1
    para PARAGRAPH1
}
FORM1 {
    edt EDIT1
    lb LISTBOX1
    cb COMBO1
    cbx CHECKBOX1
    submit SUBMIT1
}
RIGHT_FRAME {
    link LINK1
    img IMAGE1
}
IMAGE1 {
    area AREA1
}

Do opisu struktury strony WWW wydzielonych zostało kilkanaście krótkich słów kluczowych, np. edt (pole edycyjne, ang. editbox), pass (pole hasła, ang. password), lb (lista wielokrotnego wyboru, ang. listbox), cbx (pole opcji, ang. checkbox), cb (lista rozwijalna, ang. combobox), submit (przycisk przesłania formularza), link (hiperłącze, ang. hiperlink), img (obraz, ang. image). Elementy potomne względem wybranego elementu objęte są w nawiasy klamrowe. Na poziomie struktury deklaruje się jedynie obecność elementów na stronie. Nie definiuje się dla nich żadnych właściwości, gdyż to niepotrzebnie komplikowałoby kod. Dla podniesienia czytelności w powyższym przykładzie wszystkie nazwy elementów zostały zapisane dużymi literami.

3.2. Akcje użytkownika#

Testy akceptacyjne definiowane przez klienta mają najczęściej postać scenariuszy użycia. Scenariusze te są sekwencjami prostych operacji, takich jak wpisanie wartości do pola edycyjnego lub przejście do innej strony WWW przez hiperłącze. Operacje takie, nazywane również akcjami użytkownika (ang. user actions) opisywane są w języku WebTest za pomocą prostych słów kluczowych i operatorów, które nawiązują do konwencji języka C. Poniżej zamieszczone zostały przykłady kilku akcji użytkownika związanych z przykładem aplikacji z podrozdziału 2. Opis struktury strony WWW, zapisany w języku WebTest, znajduje się w podrozdziale 3.1.start ‘http://www.webtest.pl’– otwarcie w przeglądarce internetowej strony o podanym adresie URL

EDITBOX1 = ‘mgabor@z.pl’– przypisanie łańcucha znaków polu edycyjnemu

click CHECKBOX1 – naciśnięcie pola opcji (zaznaczenie, odznaczenie tego pola)

LISTBOX1 = ‘Networks’, ‘Software eng.’ – zaznaczenie dwóch opcji na liście wielokrotnego wyboru

COMBOBOX1 = ‘Introductory’– wybranie opcji z listy rozwijalnej

click SUBMIT1 – przesłanie formularza na serwer WWW

click LINK1– przejście do innej strony poprzez hiperłącze

Przypisanie lub wybranie wartości zapisywane jest zawsze przez operator „=”. Zapewnia to zwięzłość i czytelność skryptów.

3.3. Punkty weryfikacji#

Zadaniem testowania akceptacyjnego jest sprawdzanie zgodności oprogramowania z oczekiwaniami klienta. Określone przez klienta scenariusze użycia zawierają oczekiwane przez niego odpowiedzi systemu i wyniki przetwarzania. Pomiędzy opisanymi wyżej akcjami użytkownika należy więc umieścić punkty weryfikacji porównujące stan elementów stron WWW ze stanem wymaganym. Do zapisania punktów weryfikacji stosuje się proste operatory, np. „==” (równy), „!=” (różny), „=)” (zawiera). Ich znaczenie zostanie pokazane na przykładach nawiązujących do aplikacji zaprezentowanej w podrozdziale 2.PARAGRAPH1 == ‘Wrong email address’ – sprawdzenie, czy paragraf zawiera tekst „Wrong email address”

EDITBOX1 == ‘mgabor@z.pl’– sprawdzenie, czy w polu edycyjnym wpisany jest łańcuch „mgabor@z.pl”

EDITBOX1 != ‘mgabor@@z.pl’ – sprawdzenie, czy w polu edycyjnym wpisany jest łańcuch różny od „mgabor@@z.pl”

LINK1 == ‘www.onlineshop.pl’– sprawdzenie czy hiperłącze wskazuje adres URL „www.onlineshop.pl”

LISTBOX1 == ‘Software eng.’ – sprawdzenie, czy na liście wyboru zaznaczona została opcja „Software eng.”

LISTBOX1 == ‘Software eng.’, ‘Networks’ – sprawdzenie, czy na liście wyboru zaznaczone są opcje „Software eng.” oraz „Networks”

COMBO1 == ‘Introductory’- sprawdzenie, czy z listy rozwijalnej wybrana została opcja „Introductory”

LISTBOX1 =) ‘Software eng.’, ‘Networks’ – sprawdzenie, czy lista wielokrotnego wyboru zawiera opcje „Software eng.”, „Networks” (nie muszą to być jedyne opcje listy)

Przy zapisie punktów weryfikacji można również korzystać z mechanizmu prostych wyrażeń regularnych, np. sprawdzenie czy element strony zawiera lub nie zawiera danego podciągu, sprawdzenie czy element zawiera ciąg znaków zaczynający się od danego ciągu itp.

3.4. Podprogramy#

Zgodnie z XP testy akceptacyjne przygotowywane są zawsze pod dyktando reprezentanta klienta. Implementacja testów powinna zatem zawsze jasno pokazywać jego intencje. Z tego powodu zdecydowano się wprowadzić do języka WebTest mechanizm podprogramów. W skrypcie testowym zamiast skomplikowanej czasem sekwencji akcji użytkownika może pojawić się jedno czytelne wywołanie. Podprogram jest w zasadzie oddzielnym skryptem, w którym mogą znaleźć się dowolne wywołania akcji użytkownika i punkty weryfikacji. W podprogramie nie będziemy jednak z reguły umieszczać akcji „start” uruchamiającej przeglądarkę internetową.W budowanym skrypcie testowym odwołujemy się jedynie do podprogramu korzystając z operatora @, np. @InicjalizujObliczenia, gdzie nazwa InicjalizujObliczenia jednoznacznie identyfikuje podprogram do wykonania. Budowanie podprogramów jako oddzielne skrypty pozwala na wielokrotne ich użycie w implementacjach wielu przypadków testowych. Składanie skryptów z takich „klocków” zwiększa efektywność kodowania oraz ułatwia pielęgnację, gdyż unikamy zbędnej duplikacji kodu.

3.5. Stałe#

Aby maksymalnie ułatwić pielęgnację przypadków testowych zdecydowano się wprowadzić do języka WebTest mechanizm deklarowania stałych. Wartości stałych przechowywane są na zewnątrz skryptów testowych. Odwołanie się do stałej polega na użyciu operatora % i podaniu nazwy, która ją jednoznacznie identyfikuje. Dobrym przykładem wykorzystania stałych może być uruchamianie testowanej aplikacji. Zamiast umieszczać w wielu skryptach wywołanie:

    start ‘adres_URL_aplikacji’ 

można napisać

    start %identyfikator_adresu_URL

Przy przeniesieniu testowanej aplikacji na inny serwer WWW konieczna jest zmiana wartości jednej tylko stałej zamiast treści wielu skryptów.

3.6. Uwagi praktyczne#

Automatyczne testowanie aplikacji zmusza projektantów i programistów do budowania oprogramowania w sposób, który uczyni automatyzację możliwą. W przypadku aplikacji internetowych konieczne jest na przykład odpowiednie nazywanie wszystkich istotnych elementów umieszczanych na stronach WWW. Z reguły nie przywiązuje się wielkiej wagi do nazywania tabel, paragrafów czy innych podobnych elementów. Jeśli jednak będziemy chcieli zaimplementować przy pomocy języka WebTest przypadek testowy sprawdzający treść paragrafu, to musimy mieć możliwość odwołania się do niego właśnie za pośrednictwem identyfikatora.W skryptach testowych należy również oddzielać testy dotyczące struktury strony (np. zawartości listy rozwijalnej) jeśli nie będzie ona zmieniała się na skutek operacji użytkownika (struktura taka może być zmieniana przez skrypty języka JavaScript). Jeśli to możliwe, należy zapisywać takie testy w postaci oddzielnych samodzielnych skryptów lub podprogramów. Podejście takie znacznie ułatwi późniejszą pielęgnację przypadków testowych.

Podstawowym „przykrym zapachem” (ang. bad smell), który według M. Fowlera [FOWL1999] zmusza do przeprowadzania refaktoryzacji, jest duplikacja kodu. Rozwiązaniem jest wydzielanie podprogramów oraz wykorzystywanie stałych.

3.7. Przykład#

Poniżej zamieszczono skrypt języka WebTest dla testu akceptacyjnego omówionego w podrozdziale 2.

start ‘http://www.webtest.pl’, ‘WebTest Publishing House’
EDITBOX1 = ‘mgabor@@z.pl’
LISTBOX1 = ‘Networks’
COMBO1 = ‘Introductory’
click SUBMIT1
PARAGRAPH1 == ‘Wrong email address.’

Skrypt ten wydaje się być bardziej czytelny niż jego odpowiednik wygenerowany przez Rational Robota (patrz podrozdział 2). W powyższym przykładzie wyraźnie widać intencje reprezentanta klienta, zgodnie z którymi tworzone są testy akceptacyjne.

4. Uwagi implementacyjne#

Aby ułatwić tworzenie, pielęgnację i zarządzanie skryptami języka WebTest utworzono w środowisku Borland Delphi, w języku Object Pascal, niewielką aplikację. Przy projektowaniu struktury klas wykorzystano wzorce projektowe (przede wszystkim Composite oraz Factory Method) [GANG1994].Głównym elementem omawianej aplikacji jest kompilator języka WebTest. Do jego utworzenia wykorzystano generatory Lex i Yacc [CJN2002]. Schemat translacji skryptów zapisanych w języku WebTest przedstawiono na rysunku 2. Translator, na wejście którego podajemy skrypty języka WebTest, tworzy w pamięci operacyjnej hierarchie obiektów opisujących strukturę stron WWW, akcje użytkownika i punkty weryfikacji. Dopiero na podstawie tych obiektów tworzone są elementy wymagane przez środowisko Rational Robot, a więc skrypty języka SQABasic, opisy przypadków testowych w bazie danych programu i w plikach formatu XML oraz pliki VPM i GRD (format tych plików jest specyficzny dla Rational Robota), w których opisane są punkty weryfikacji. Nazwy punktów weryfikacji wykorzystywane przez Rational Robota tworzone są automatycznie.

fig2.png

Rys. 2. Schemat działania translatora języka WebTest

Rational Robot oferuje dwa typy punktów weryfikacji: Object Data i Object Properties. Weryfikacja typu Object Data dotyczy tego CO jest wyświetlane w oknie przeglądarki, natomiast Object Properties służą do badania JAK coś jest wyświetlane (kolor, czcionka itp.). Niestety, opisywany translator potrafi tworzyć punkty weryfikacji jedynie typu Object Data. Na obecnym etapie nie wiemy jak w prosty sposób implementować punkty weryfikacji typu Object Properties, gdyż informacje o nich zapisywane są w plikach binarnych o skomplikowanej strukturze.

5. Maskowanie wyników przetwarzania#

Dokumenty będące wynikiem przetwarzania zawierają czasem dane zmieniające się niezależnie od akcji użytkownika i danych wejściowych. Przykładem może być data pojawiająca się na fakturze (patrz rysunek 3). Jeśli powtórzymy test dzień po jego stworzeniu, to dokładne porównanie wartości wyjściowych z oczekiwanymi zasygnalizuje błąd, mimo że wszystkie dane na fakturze, za wyjątkiem daty, będą zgodne. W dalszej części artykułu dane takie nazywać będziemy elementami zmiennymi. Na rysunku 3. mamy trzy elementy zmienne: numer faktury, datę jej wystawienia i termin płatności.

fig3.png

Rys. 3. Przykład faktury zapisanej do pliku tekstowego

Znane są trzy sposoby rozwiązania zarysowanego powyżej problemu [GRAH1999]:

  • Proste maskowanie. Element zmienny identyfikowany jest przez podanie numeru linii, w której występuje oraz przez podanie indeksu jego pierwszego i ostatniego znaku. Wróćmy do przykładu faktury zaprezentowanej na rysunku 3. Proste maskowanie miałoby postać następujących instrukcji:
IGNORE (1, 16, 25)
IGNORE (3, 7, 17)
IGNORE (12, 12, 22)
  • Maskowanie kontekstowe. Element zmienny identyfikowany jest przez podanie ciągu znaków poprzedzających element oraz liczby znaków składających się na niego. Maskowanie kontekstowe dla rozważanego powyżej przykładu mogłoby mieć postać:
IGNORE_AFTER („Faktura nr ”, 10)
IGNORE_AFTER („Data: ”, 11)
IGNORE_AFTER („Płatne do: ”, 11)
  • Wyrażenia regularne. Element zmienny opisany jest za pomocą wyrażenia regularnego. W rozważanym przykładzie moglibyśmy wykorzystać następujące wyrażenia:
F[[0-9]{4}\/20[[0-9]{2}
[[0-9]{2}\-[[A-Z]{3}\-20[[0-9]{2}
[[0-9]{2}\-[[A-Z]{3}\-20[[0-9]{2}

Wadą prostego maskowania i maskowania kontekstowego jest wrażliwość na zmiany w dokumentach generowanych przez testowany system. Załóżmy na przykład, że z wzorca faktury chcemy usunąć „nr” lub dodać po słowie faktura zwrot „pro forma”. Zmieni się wówczas położenie elementu zmiennego. Należałoby teraz odnaleźć i zmodyfikować wszystkie skrypty testowe odwołujące się do tego elementu. Wyrażenia regularne wydają się być lepszym rozwiązaniem, ale nie są bez wad. Jeśli chcielibyśmy zmodyfikować format wyświetlanej daty, czy też format numeru faktury, to znów musielibyśmy znaleźć i zmodyfikować wszystkie skrypty testowe odwołujące się do tych elementów. Ponadto w przypadku wyrażeń regularnych istnieje groźba zignorowania elementów, które nie są elementami zmiennymi, lecz mają podobną do nich budowę. Jeśli, na przykład dla faktury z rysunku 3., datę opisalibyśmy wyrażeniem [0-9\-A-Z]+, to w czasie porównania wyników przetwarzania z danymi oczekiwanymi pominięte zostałyby także symbole produktów oraz ich ceny. Istotą proponowanego przez nas rozwiązania jest wprowadzenie języka opisu szablonów dokumentów. Sprawdzenie poprawności wygenerowanego (aktualnego) dokumentu odbywa się na podstawie jego wzorca (patrz rysunek 5). Przykładowy szablon zapisany w proponowanym języku przedstawiono na rysunku 4. Odpowiada on fakturze z rysunku 3. Szablon został podzielony na dwie części:

  • Część deklaracyjna. Deklarowane są tu wyrażenia opisujące maskowane elementy. Deklaracje te oparte zostały na wyrażeniach regularnych zaczerpniętych z języka AWK.
  • Ciało szablonu. Kolejne linie ciała szablonu odpowiadają kolejnym liniom opisywanego dokumentu. Elementy zmienne reprezentowane są za pomocą nazwy poprzedzanej symbolem „#”. Nazwa ta jest nazwą wyrażenia regularnego i jest zdefiniowana w części deklaracyjnej.

fig4.png

Rys. 4. Przykład szablonu maskowania danych dla faktury zaprezentowanej na rysunku 3.

fig5.png

Rys. 5. Schemat “ideowy” porównania na bazie szablonów

Proponowane rozwiązanie separuje dane służące weryfikacji poprawności przetwarzania od skryptów testowych. W skryptach języka WebTest umieszcza się jedynie komendę COMPARE, której parametrami są: nazwa pliku zawierającego szablon dokumentu oraz nazwa pliku z aktualnym dokumentem. Modyfikując dokument taki jak faktura, wystarczy wprowadzić zmiany tylko do jednego pliku zawierającego szablon faktury. Wszystkie skrypty testowe odwołujące się do faktury automatycznie dostosują swoje działanie do nowej sytuacji.Proponowana metoda, w odróżnieniu od prostego i kontekstowego maskowania, pozwala dodatkowo na tzw. „miękkie” maskowanie, w którym ignorujemy wartości pól takich jak data, kontrolując jednocześnie ich składnię (format). Warto też zauważyć, że klasyczne metody maskowania, w przeciwieństwie do proponowanej, nie dają możliwości sprawdzenia, czy elementy zmienne w ogóle się pojawiły w badanych dokumentach.

6. Implementacja maskowania opartego na szablonach#

Schemat implementacji porównania na bazie szablonów przedstawiono na rysunku 6.

fig6.png

Rys. 6. Schemat implementacyjny porównania na bazie szablonów

Na podstawie szablonu program napisany w języku Lex generuje program (komparator) w języku AWK. Wygenerowany program wraz z aktualnym dokumentem stanowi wejście dla interpretera AWK (gawk.exe). Komparator przepisuje do raportu porównania wszystkie linie, które nie są zgodne z dostarczonym szablonem dokumentu. Raport zapisany zostaje do pliku dyskowego. Jeśli plik ten jest pusty, to następuje jego skasowanie. Jednocześnie w skrypcie SQABasica umieszczany jest punkt weryfikacji sprawdzający istnienie tego pliku. Jeśli wyniki przetwarzania nie są zgodne z dostarczonym szablonem, to Rational Robot znajdzie plik z raportem porównania i zgłosi błąd wykonania skryptu testowego. Analiza raportu porównania wskaże elementy niezgodne z oczekiwaniami.Przykładowy komparator, odpowiadający szablonowi z rysunku 4. zamieszczony został na rysunku 7. Szarym kolorem zaznaczono elementy zmienne. Część programu zapisana czcionką pogrubioną (deklaracje po słowie BEGIN) odpowiada części deklaracyjnej rozważanego szablonu. Wykorzystanie „dynamicznych wyrażeń regularnych” pozwala stosunkowo łatwo wygenerować program (komparator) w języku AWK na podstawie szablonu dokumentu oraz podnosi czytelność samego programu. W poniższym przykładzie odzwierciedlone zostały wszystkie wiersze szablonu dokumentu (również wiersze puste). Niektóre znaki wykorzystywane w szablonach dokumentów (np. „|” ) mogą być znakami specjalnymi języka AWK, służącymi do zapisu wyrażeń regularnych. Przy automatycznej generacji komparatora wszystkie takie znaki muszą być odpowiednio zapisywane, na przykład poprzedzane znakami „\”.

fig7.png

7. Podsumowanie#

Programowanie Ekstremalne (XP) zaleca automatyzowanie wszystkich testów (również testów akceptacyjnych) tworzonych w procesie rozwoju oprogramowania. W rozdziale przedstawiono propozycję języka skryptowego WebTest służącego do opisu testów akceptacyjnych dla aplikacji internetowych tworzonych zgodnie z głównymi praktykami XP (testy akceptacyjne tworzone pod dyktando reprezentanta klienta, przyjęcie za główną miarę postępu prac liczbę pozytywnie wykonanych testów akceptacyjnych, częste wykonywanie testów akceptacyjnych). Przy projektowaniu języka skryptowego szczególny nacisk położono na jego czytelność i mechanizmy pozwalające maksymalnie ułatwić pielęgnację przypadków testowych. Dzięki opracowanemu translatorowi skrypty zapisane w języku WebTest wykonywane są w środowisku Rational Robota, co wzbogaca możliwości tego ciekawego narzędzia.Obecnie przy współpracy Działu Inżynierii Oprogramowania poznańskiej firmy Bestcom Sp. z o.o. rozważamy różne aspekty związane z budowaniem i pielęgnacją automatycznych przypadków testowych. Zamierzamy rozbudować język WebTest i jego translator (istotne jest wybranie odpowiednich środków wizualizacji skryptów). W przyszłym roku zamierzamy wprowadzić język WebTest do projektów realizowanych w ramach Studia Rozwoju Oprogramowania [NAWR1998] na Politechnice Poznańskiej.

Bibliografia#

[BECK2001] K. Beck, Wydajne programowanie, Mikom, Warszawa, 2002.
[CJN2002] J. Cybulka, J. Jankowska i J. Nawrocki, Automatyczne przetwarzanie tekstów. AWK, LEX i YACC, Nakom, Poznań, 2002.
[FOWL1999] M. Fowler, Refactoring: Improving the Design of Existing Code,Addison-Wesley, 1999.
[GANG1994] E. Gamma, E. Helm, E. Johnson i E. Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley, 1994.
[GRAH1999] M Fewster i M Graham, Software test automation, Addison-Wesley, 1999.
[JEFF1999] R. Jeffries, eXtreme Testing: Why aggressive software development calls for radical testing effort, STQE Magazine, March/April, 1999.
[JEFF2001] R. Jeffries, R. Anderson i R. Hendrickson, Extreme Programming Installed, Addison-Wesley, Boston, 2001.
[NAWR1998] J. Nawrocki, Towards educating leaders of software teams, w: P. Klint, J. Nawrocki (eds), Software Engineering Education Symposium SEES’98, Poznań, 1998, Scientific Publishers OWN, Poznań, 149-157.
[NIST2002] RTI, National Institute of Standards & Technology, The Economic Impacts of Inadequate Infrastructure for Software Testing, Final Report, May 2002, http://www.nist.gov/director/prog-ofc/report02-3.pdf.
[PIPK2002] J. U. Pipka, Refactoring in a “Test First”-World, The Third International Conference on eXtreme Programming and Agile Processes in Software Engineering, 2002, http://www.xp2003.org/xp2002/index.html.
[ROBO2001] Rational Software Corporation, Using Rational Robot, 2001.

[#1] Praca finansowana przez KBN w ramach grantu 4 T11F 001 23 realizowanego w latach 2002-2005.

©2015 e-Informatyka.pl, All rights reserved.

Built on WordPress Theme: Mediaphase Lite by ThemeFurnace.