tester.pl - numer 10
DESCRIPTION
TRANSCRIPT
Od redaktora Jak ten czas leci, zanim się obejrzeliśmy, a tu juŜ 10 – jubileuszowy – numer naszego
kwartalnika. Mam nadzieje, ze numer jubileuszowy jest równie ciekawy jak 9 poprzednich.
W tym numerze cztery ciekawe artykuły:
1. Joanna Droździel o zarządzaniu zmianą – jest to kontynuacja jej pracy
z poprzedniego numeru
2. Moty Aharonovitz o tym jak skutecznie usprawnić testowanie oparte na
wymaganiach
3. Mateusz Bukowski i Paweł Paterek o obiektach pozornych, ciekawe rozwiązanie
związane z metodologią TDD; autorzy bardzo dokładnie na przykładzie opisują na
czym to polega
4. Maciej Dusza o pisaniu dokumentacji – coś czego większość z nas nie lubi, autor pokazuje jak robić to dobrze
Zgodnie z rozpoczętym w numerze 8 kwartalnika cyklem zamieszczamy w tym numerze
sprawozdanie z konferencji, które odbyły się ostatnio: Łukasz śebrowski był w Düsseldorfie na
SQS Software & Systems Quality Conferences i relacjonuje nam to wydarzenie.
W czasie tworzenia tego numeru odbyła się IV Konferencja Jakości Systemów
Informatycznych. Na gorąco moŜna jedynie powiedziec, ze była bardzo ciekawa – więcej o niej
w następnym numerze Testera.PL
Równocześnie chciałbym – kolejny raz - gorąco zachęcić wszystkich czytelników tego
periodyku do aktywnej współpracy. Cały czas czekamy na Państwa uwagi, artykuły, felietony –
wszystko, co Was interesuje, co chcielibyście przeczytać, czego się dowiedzieć. JeŜeli tylko
będziemy mogli, postaramy się zrealizować Państwa postulaty.
TESTER.PL
Strona 2 z 63
Zarządzanie problemem i incydentem
Joanna Droździel
Joanna Droździel jest absolwentem Informatyki na
Wydziale Elektrycznym Politechniki Warszawskiej. Obroniła pracę magisterską z zakresu metodyki ITIL. Posiada certyfikat ISEB Foundation.
Od października 2006 roku prowadzi blok wykładów „Zarządzanie usługami IT” na Podyplomowym Studium Prowadzenia Projektów Informatycznych na Politechnice Waszawskiej. Obecnie pracuje w firmie CS Stars na stanowisku starszego analityka do spraw zapewnienia jakości, biorąc udział w projektach dla klientów zagranicznych.
TESTER.PL
Strona 3 z 63
Zarządzanie zmian ą Joanna Droździel
Tak jak Ŝycie społeczne i cywilizacja poddane są nieustannej ewolucji, tak równieŜ i w
działalności firmy zmiany informatyczne są konieczne. To czy siły wywołujące zmiany mają
charakter ekonomiczny, techniczny, społeczny czy polityczny nie ma szczególnego znaczenia.
Zmiany wdraŜane w sektorze informatycznym dotyczą przede wszystkim infrastruktury oraz
oprogramowania, powstają najczęściej w trakcie standaryzacji działań produkcyjnych lub teŜ
wynikają z potrzeby zapanowania nad zgłoszeniami uŜytkowników. JeŜeli jeszcze klika lat temu
pomysł wykorzystania informatyki w projektach elektronicznej administracji spotykał się z
ogólnym niedowierzaniem, to teraz pomysł ten juŜ nikogo nie dziwi. Wręcz przeciwnie, uwaŜa
się Ŝe wykorzystanie informatyki w administracji przedsiębiorstwa nie będzie efektywne, jeŜeli w
projektach elektronicznej administracji nie będą uwzględnione zmiany, jakim we współczesnym
świecie ulega firma.
Proces zarządzania zmianą
Bez efektywnego procesu zarządzania zmianą dalszy rozwój cywilizacyjny byłby
niemoŜliwy. Dlatego jeŜeli w jakiejś dziedzinie Ŝycia nie spotkaliśmy się z koniecznością
wprowadzania zmian, to wcześniej czy później będziemy do tego zmuszeni. W wyniku
zachodzących na świecie przemian: społecznych, cywilizacyjnych, ekonomicznych czy
kulturowych zmieniają się takŜe obszary podległe działalności organizacji. Proces zarządzania
zmianami w sektorze usług informatycznych jest nieodłącznym elementem działalności
biznesowej przedsiębiorstwa. Gdy proces ten przebiega źle, wówczas oddziałuje to negatywnie
równieŜ na stronę biznesową. Bez efektywnie przeprowadzonych zmian informatycznych
zakłócona zostaje działalność biznesowa firmy. MenedŜer działu informatycznego często
twierdzi, Ŝe kierowany przez niego zespół jest przygotowany na realizację procesu zmian. Z
badań wynika, Ŝe nierzadko jest inaczej. MenedŜerowie radzą sobie z oceną i monitorowaniem
efektów wprowadzonych zmian. Gorzej jest jednak z wywołaniem kryzysu, czyli stworzeniem
impulsu do zmiany, czy teŜ z wprowadzeniem nowego porządku rzeczy, gdy sytuacja tego
wymaga.
TESTER.PL
Strona 4 z 63
KaŜda zmiana pociąga za sobą lawinę kolejnych. Dlatego ci, którzy ponieśli straty
finansowe, wiedzą jak waŜny jest dobrze przeprowadzony proces zarządzania zmianą. PomoŜe
on zbadać ryzyko wprowadzenia zmiany, oszacować ilość odpowiednich zasobów oraz
sprawdzić, czy czas wprowadzenia zmiany został właściwie określony. Mając na celu przede
wszystkim minimalizację liczby incydentów i problemów wynikających ze źle wprowadzonych
zmian. W pracach nad pozostałymi procesami menedŜerowie mogli skorzystać z pomocy
konsultantów, w przypadku procesu zarządzania zmianą pomoc ta moŜe okazać się
bezwartościowa. Wynika to z faktu iŜ tylko osoba przebywająca w danej organizacji jest w stanie
poznać realia rządzące firmą i dzięki temu określić kierunek koniecznych zmian.
Poznając procesy metodyki ITIL zauwaŜamy, iŜ kolejny proces zaleŜy od poprzedniego i
wpływa na następny, podobnie jest równieŜ z procesem zarządzania zmianą, który w większym
lub mniejszym stopniu korzysta, oddziałuje, wpływa na pozostałe procesy. Konieczność
zwiększenia pojemności usług lub teŜ utrzymanie jej na dotychczasowym poziomie (ale przy
większej liczbie uŜytkowników, bądź ilości danych oraz liczby transakcji), moŜe wymusić
konieczność wprowadzenia zmian.
Procesy te nie będą działać efektywnie bez poprawnie przeprowadzonego procesu
zarządzania zmianą, który w duŜej mierze zaleŜy od procesów zarządzania problemem oraz
incydentem. Wynika to z ilości zmian zgłoszonych przez uŜytkowników na skutek wykrytych
awarii, jak równieŜ powstałych na skutek działań proaktywnych w procesach zarządzania
incydentem i problemem.
Podstawą procesu zarządzania zmianą jest prośba o zmianę (RfC), od której rozpoczyna
się proces. Kluczem do efektywnego wdroŜenia zmiany jest odpowiednio wypełniony formularz
w wersji papierowej bądź elektronicznej. Wersja papierowa bardzo szybko okazała się
niepraktyczna, zwłaszcza w firmach, gdzie liczba zgłaszanych zmian jest bardzo duŜa.
Poszczególne etapy procesu odbywają się drogą elektroniczną za pomocą odpowiedniej
aplikacji.
Przystępując do procesu zarządzania zmianą warto tuŜ przed wdroŜeniem
zaplanowanego modelu postępowania zabezpieczyć aktualny stan aplikacji, sprzętu czy
konfiguracji. Z kaŜdej nieudanej zmiany moŜna się wycofać, ale tylko wtedy, gdy dysponujemy
szczegółami sprzed wprowadzenia zmian. Są jednak zmiany, które aby mogły być
zaimplementowane, wymagają jednak wielu konsultacji. NaleŜy wówczas skorzystać z pomocy
organu Rada Doradcza (CAB), w skład której wchodzą nie tylko menedŜer zmiany i
przedstawiciele zarządu, ale równieŜ osoby odpowiedzialne za pozostałe procesy metodyki ITIL.
Rozpoczynając wdroŜenie procesu w firmie warto rozpocząć od niewielkich, lekko
skomplikowanych zmian i dopiero wraz z upływem czasu sięgać po zmiany bardziej złoŜone.
TESTER.PL
Strona 5 z 63
Dzięki takiej postawie, menedŜerowie opanują zasady, jakimi kieruje się proces zarządzania
zmianą na tyle dobrze, by móc go przeprowadzać w sposób mechaniczny. Proces zarządzania
zmianą został przedstawiony na rysunku poniŜej.
Rysunek 1. Proces zarządzania zmianą.
Proces zarządzania zmianą funkcjonuje dzięki osobie odpowiedzialnej za jego poprawne
zaplanowanie oraz wdroŜenie. Tą osobą jest menedŜer zmiany a zarazem właściciel procesu.
MenedŜer zmiany odpowiada za realizację juŜ zaplanowanych zmian, planowanie następnych,
nadzór nad zmianami przeprowadzonymi, a więc generowanie raportów dla strony biznesowej
oraz przedstawienie argumentów potwierdzających potrzebę planowania zmian. Autorzy
metodyki ITIL warunkują sukces we wdroŜeniu metodyki od indywidualnych działań właściciela
procesu. Z reguły ilość pracy przekracza jednak moŜliwości jednej osoby. Dlatego teŜ waŜne jest
aby menedŜer dowolnego procesu zaangaŜował do pracy tyle osób, ile jest w danej chwili
niezbędnych (uwzględniając moŜliwości finansowe przedsiębiorstwa). Z reguły na etapie
planowania menedŜer korzysta z pomocy analityków a potrzebne informacje czerpie z Bazy
Konfiguracji. Natomiast na etapie wdroŜenia zmiany korzysta z pomocy programistów,
administratorów, testerów, a więc osób dostępnych w ramach codziennej działalności
organizacji.
Jednak nie wszystkie zmiany są wynikiem efektywnej pracy menedŜera zmiany, wiele
próśb o zmianę pochodzi bezpośrednio od uŜytkowników. Zaleca się by co pewien czas zapytać
uŜytkowników jakich zmian oczekują. Nawet jeŜeli w danej chwili brakuje moŜliwości ich
TESTER.PL
Strona 6 z 63
realizacji, mogą stać się pomocne na etapie planowania przyszłych zmian. Bardzo wiele zgłoszeń
nie moŜe zostać zrealizowanych ze względu na ograniczenia ustalone w umowie SLA pomiędzy
klientem a dostawcą usług informatycznych. Warto jednak wszystkie zgłoszenia zachowywać
poniewaŜ mogą one stać się źródłem bardzo cennej wiedzy w chwili wykonywania kolejnego
przeglądu umowy. Równie istotne dla procesu zmian są wyniki badań opinii klientów gdyŜ to ich
zdanie w decydującym stopniu powinno wyznaczać kierunek wewnętrznych zmian. Powinny to
być badania systematyczne, a ich rezultaty muszą być moŜliwie szybko uwzględniane w
projektach zmian, tak aby w efekcie przyniosły klientowi satysfakcję wcześniej, niŜ działania
rynkowe konkurencji
Komunikacja oraz informacja
W procesie zarządzania zmianą kluczową rolę odgrywa informacja oraz komunikacja. W
aspekcie związanym z informacją waŜne jest, by osoba odpowiedzialna za realizację procesu
dysponowała gruntownym przygotowaniem merytorycznym. MenedŜer odpowiedzialny za
proces zarządzania zmianą podejmując decyzję musi kierować się regułą: im więcej informacji
tym lepiej. Podobnie jest z drugą istotną kwestią w procesie zarządzania zmianą - komunikacją.
W przypadku niewielkiej zmiany, której wpływu uŜytkownik nie odczuje w swojej codziennej
pracy, aspekt ten nie odgrywa tak waŜnej roli. Nie chodzi bynajmniej o uświadomienie
uŜytkownika, Ŝe zmiana jest planowana, ale równieŜ o czynny jego udział w pracach nad
procesem. Tak naprawdę ludzie znacznie częściej przeciwstawiają się zmianom, niŜ je akceptują.
Dlatego by wywołać reakcje pozytywne, naleŜy zaangaŜować większą grupę pracowników w
proces zarządzania zmianą. Dzięki takiej postawie uzyskamy zrozumienie konieczności
wprowadzania zmian, a co za tym idzie, wiarę w powodzenie całej misji. By uniknąć
negatywnych reakcji uŜytkowników na wprowadzenie zmian bądź ich brak naleŜy poprawić
komunikację na linii uŜytkownik - zarząd. Tylko dzięki pełnej jasności i klarowności działań
uzyskamy lepsze zrozumienie sytuacji. Czasami jednak radykalna zmiana jest łatwiejsza do
zaakceptowania dlatego, Ŝe niewiele elementów nowej strategii przypomina stare procedury.
Istotnym czynnikiem wpływającym na reakcję na zmianę jest czas. Im wolniej przebiegają
zmiany, tym dotkliwiej są one odczuwane przez pracowników.
Ryzyko wprowadzanych zmian
Wielu dyrektorów słysząc słowo „zmiana” reaguje bardzo nieufnie. Zmiana kojarzy im się
ze stresem oraz chaosem w działalności przedsiębiorstwa. Tak być nie musi, wystarczy, Ŝe
więcej uwagi skierują na etap planowania, a nie jak to było zazwyczaj dopiero na etap realizacji.
TESTER.PL
Strona 7 z 63
W praktyce jednak rzadko zdarza się by wprowadzenie zmian było poprzedzone
formalnym procesem. Być moŜe jest to jedną z głównych przyczyn późniejszych negatywnych
skutków innowacji. Aby uniknąć niespodzianek warto przed wdroŜeniem zaplanować krok po
kroku sposób wprowadzania zmiany oraz opracować wszystkie warianty postępowania na
wypadek awarii.
Realizując proces zarządzania zmianą nie sposób nie otrzeć się o ryzyko poraŜki, kaŜda
zmiana moŜe bowiem zakończyć się niepowodzeniem i kaŜdy menedŜer zmiany musi mieć tego
świadomość. Co zrobić by tego uniknąć? Przede wszystkim wyeliminować sytuacje, w których
działamy w pośpiechu i w warunkach improwizacji. Zmiany powinny być planowane z
wyprzedzeniem. MenedŜer zmiany powinien opracować Plan Zmian (FSC) na okres np. jednego
miesiąca, w którym wskaŜe zarówno elementy konfiguracji i infrastruktury, jak i osoby, których
wprowadzane zmiany będą bezpośrednio dotyczyły. Tylko takie postępowanie daje szansę
uniknięcia ewentualnej poraŜki. Celem menedŜera zmian jest zablokowanie zmian
krótkowzrocznych, a więc takich, które w pierwszej chwili wydają się być dobrym rozwiązaniem,
jednak w szerszej perspektywie nie są nim.
Oczywiście takie postępowanie moŜe być skuteczne w przypadku zmian standardowych
czyli takich, które nie są wymuszone krótkim terminem wykonania. Co zrobić w przypadku zmian
pilnych? Jak wówczas uchronić organizację przed ryzykiem poraŜki? Przede wszystkim naleŜy
zachować zimną krew; nawet w krótkim okresie realizacji procesu zarządzania zmianą nie
powinno dojść do pominięcia Ŝadnego z etapów procesu. Pominięcie któregokolwiek z kroków
powoduje automatycznie wzrost ryzyka.
Słownik
CAB - Change Advisory Board
FSC - Forward Schedule of Changes
ITIL - Information Technology Infrastructure Library
SLA - Service Level Agreement
RfC - Request for Change
TESTER.PL
Strona 8 z 63
Jak skutecznie usprawni ć testowanie oparte na wymaganiach (Requirements Based Testing - RBT)
Moty Aharonovitz – Borland Software Corporation
Moty Aharonovitz pracuje jako senior director of Product Strategy w firmie Borland.
Ma ponad 15 lat doświadczenia w pracy nad rozwojem oprogramowania, dzięki czemu aktywnie
wspiera i rozwija wizję Optymalizacji Dostarczania Oprogramowania (SDO) w
przedsiębiorstwach i firmach informatycznych oraz czynnie wspiera rozwiązania z zakresu
Zarządzania Jakością w Cyklu śycia aplikacji.
Kontakt: [email protected].
TESTER.PL
Strona 9 z 63
Jak skutecznie usprawni ć testowanie oparte na wymaganiach (Requirements Based Testing - RBT)
Moty Aharonovitz – Borland Software Corporation
Naszym głównym zadaniem jako menedŜerów ds. jakości oraz testerów jest znajdowanie
błędów w tworzonym oprogramowaniu. Na szczęście obecnie praca wielu z nas wykracza juŜ
poza ujawnianie oraz śledzenie „pluskw” i obejmuje bardziej krytyczne zagadnienia związane ze
sprawdzaniem, czy oprogramowanie które będzie wytwarzać nasza firma (jeszcze przez jego
finalnym wyprodukowaniem) spełni oczekiwania uŜytkowników. Aby tego dokonać wiele
organizacji zaczęło wykorzystywać Testowanie Oparte Na Wymaganiach (RBT).
Dzięki zastosowaniu RBT praca zespołów testowych staje się efektywniejsza - testy
bezpośrednio nawiązujące do konkretnych wymagań funkcjonalnych umoŜliwiają skuteczne
dotarcie do źródła problemu poprzez bezpośrednie powiązanie z wymaganiami na dowolnym
etapie cyklu Ŝycia aplikacji. W rezultacie otrzymujemy systematyczne i efektywne pokrycie
obszaru testów, co sprawia, Ŝe w zasadzie testujemy to, co ma największe znaczenie dla
naszego klienta.
Wyzwanie jakie napotykamy, wdraŜając RBT w naszej organizacji, to dopasowanie go do
istniejących procesów Działu Jakości i dotychczasowych praktyk testowania. Z własnego
doświadczenia mogę zaproponować trzy praktyczne sugestie, jak ulepszyć podejście RBT:
1. Testujmy wcześnie i często, tak aby testowanie stało się czynnością równoległą do
procesu tworzenia, rozciągało na wszystkie role, uświadamiając wszystkim uczestnikom i
sponsorom projektu znaczenie jakości.
2. Testujmy z głową, nie instynktownie - zapewniając metodyczność i powtarzalność w
planie testów zwiększamy przewidywalność i mierzalność procesu testowania.
3. Testujmy z wykorzystaniem metryk - pozwoli to określić status produkcji i działalności
IT, umoŜliwiając zarządowi wgląd w stan wszystkich projektów IT w firmie oraz właściwie
ocenić nasz wkład i zaangaŜowanie.
TESTER.PL
Strona 10 z 63
Kryzys jakości
Wiele analiz, w tym te opracowane przez Standish Group Chaos Report, opisuje dotychczasowe
standardy w przemyśle IT: większość projektów IT wykracza poza załoŜony czas oraz budŜet.
Niewystarczająca jakość wytwarzanego oprogramowania jest najwaŜniejszym czynnikiem
odpowiedzialnym za niepowodzenia i często prowadzi do przebudowania kodu, wpływając na
zakres i jakość produktu finalnego. Ponowne praca nad tymi samymi fragmentami kodu wydłuŜa
czas powstawania aplikacji i znacząco pochłania zasoby, takŜe finansowe. Aby zmniejszyć
zagroŜenia wynikające z błędów, koniecznie musimy zdać sobie sprawę z coraz silniejszych
tendencji dbania o jakość powstających aplikacji juŜ od samego początku ich Ŝycia.
Doświadczenia firm z branŜy IT oraz badania trendów rynkowych jasno wskazują na dwa
podstawowe powody niskiej jakości tworzonych aplikacji:
1.) źle sformułowane wymagania
oraz
2.) niewłaściwe ich pokrycie przez testy.
Wady w specyfikacji wymagań
Wielu z nas często spotyka się ze skargami uŜytkowników stwierdzających ewidentne braki w
oprogramowaniu, które przeszło przez rygorystyczną kontrolę działu jakości i szereg testów.
Najczęstszy powód? Wymagania były niewłaściwie sformułowane juŜ od samego początku
projektu.
Wymagania do rozbudowanych systemów często są ustalane w dwóch równoległych procesach,
które następnie ewoluują równolegle w całym cyklu Ŝycia aplikacji. Wspomniane dialogi
powstają w wyniku postawienia sobie dwóch pytań: "co potrzebujemy zbudować?” oraz "co
moŜemy zbudować?” Jakość tych dialogów często określa ostateczną jakość budowanej
aplikacji.
Badania wykonane przez Jamesa Martina1 pokazują, Ŝe 56 procent wszystkich
zidentyfikowanych błędów w projektach informatycznych ma swoje korzenie w fazie tworzenia
wymagań. To samo badanie wykazuje, Ŝe około połowę błędów powstaje w wyniku niewłaściwie
napisanych, dwuznacznych, niejasnych i niepoprawnych wymagań. Druga połowa wad
oprogramowania moŜe zostać przypisana niewystarczającej specyfikacji (np. braku wymagań,
1 James Martin, “An Information Systems Manifesto”
TESTER.PL
Strona 11 z 63
które po prostu zostały pominięte w fazie analizy).
Wykres 1: Dystrybucja Wad w Projektach Oprogramowania
Inne studia ujawniają podobne odkrycia:
82 procent przypadków wielokrotnie tworzonego kodu jest związanych się z błędami w
wymaganiach2
Problemy w obszarze wymagań w 44 procentach przypadków są powodem odwołania
projektu3
Tylko 54 procent początkowych wymagań projektowych jest właściwie zrozumiane4
Tylko 45 procent zebranych wymagań zostaje właściwie uŜyte5
Podsumowując moŜemy stwierdzić, Ŝe dwa najwaŜniejsze problemy związane z jakością
wymagań to:
• wymagania i specyfikacje są niekompletne (z powodu braku informacji od uŜytkowników
i sponsorów)
• zebrane wymagania są nienajlepszej jakości (głównie w wyniku braku zrozumienia
potrzeb obu stron, znalezienia wspólnego języka oraz metod skutecznej weryfikacji
zebranych załoŜeń).
Problemy z pokryciem wymagań testami
2 Martin & Leffinwell 3 Standish Group: Chaos Report 4 Standish Group: Chaos Report 5 Jacobs
TESTER.PL
Strona 12 z 63
Kiedy temat jakości pojawia się na końcowym etapie cyklu wytwarzania aplikacji, testowanie
wymaga uprzedniego zakończenia fazy kodowania. W tym momencie zespół testerów znajduje
się pod presją czasu, a ich zadaniem staje się jak najszybsze zweryfikowanie poprawności
funkcjonalnej aplikacji. Ten etap często postrzegany jest jako wąskie gardło, które opóźnia
wdroŜenie aplikacji. W takich warunkach nie tylko trudnym jest upewnienie się, co do
poprawności wymagań, ale przede wszystkim ułoŜenie takiego test planu, który zapewni
poprawność i pełne pokrycie wymagań, jak równieŜ widoczność róŜnych aspektów jakościowych
testowanej aplikacji. Oczywiste jest, Ŝe praca testera przy powyŜszych załoŜeniach staje się
nieefektywna i, co tu ukrywać, frustrująca.
Osobnym wyzwaniem jest osiągnięcie zadowalającego poziomu pokrycia testami. ZłoŜoność
dzisiejszych aplikacji stanowczo nam w tym nie pomaga. Coraz trudniejsze staje się wykonanie
wszystkich moŜliwych scenariuszy, głównie ze względu na liczbę alternatywnych ścieŜek
przechodzenia przez aplikację. Jakakolwiek próba usystematyzowania (lub zautomatyzowania)
procesu połączenia wszystkich moŜliwych przypadków doprowadza nas po prostu to tak duŜej
liczby kombinacji scenariuszy testowych, Ŝe testowanie staje się bardzo trudnym i
długotrwałym, a przez to i nieopłacalnym z punktu widzenia organizacji zadaniem.
W dodatku, w wielu przedsiębiorstwach zarządzanie zmianą, głównie ze względu na
częstotliwość i skalę zmian w wymaganiach, staje się coraz trudniejsze. Stąd bez odpowiedniego
wsparcia w zakresie zarządzania zmianą, często gubimy się jeśli chodzi o śledzenie powiązań
pomiędzy zmieniającymi się wymaganiami oraz odzwierciedlenia tych zmian w przypadkach
testowych.
Sprawdzone praktyki RBT
Podejście RBT, jeśli zostało właściwie zdefiniowane, adresuje bezpośrednio zaleŜność
pomiędzy testami funkcjonalnymi a źródłem znalezionych błędów. Nawet, jeśli nasza organizacja
nie uŜywa podobnych praktyk dzisiaj, większości z nas zapewne nie są obce procesy
uwzględnione na poniŜszym wykresie.
TESTER.PL
Strona 13 z 63
Wykres 2: Przebieg procesu RBT
Równolegle z aktualnymi procesami testowymi, organizacje mogą spróbować zaadoptować
następujące praktyki RBT:
1. Testujmy wcześnie i często
W momencie, gdy mamy przygotowane wymagania oraz gotowy projekt i fragmenty kodu,
przejrzyjmy je pod kątem celów biznesowych, przypadków uŜycia (use cases) i przypadków
testowych (test cases). Starajmy się testować nasz projekt na jak najwcześniejszym etapie,
poniewaŜ usterki zlokalizowane we wczesnych fazach rozwoju projektu są tańsze i łatwiejsze do
usunięcia, w wyniku czego moŜemy się spodziewać znacząco mniejszej ilości „niespodzianek” na
dalszych jego etapach. Testowanie powinno stać się czynnością równoległą do procesu
tworzenia aplikacji. W ten sposób sponsorzy projektu w większym stopniu uświadomią sobie rolę
jakości w całym procesie. Dzięki takiemu podejściu, testowanie będzie postrzegane juŜ nie jako
tzw. „wąskie gardło” w produkcji oprogramowania, a bardziej jako kluczowy czynnik w ogólnym
procesie zapewnienia jakości powstających systemów.
PoniewaŜ sukces projektu informatycznego moŜe być bezpośrednio powiązany z solidnym
zrozumieniem i zdefiniowaniem wymagań, promowanie RBT staje się doskonałą wizytówką firm
dbających o jakość swoich produktów. Najlepsze praktyki w procesie Jakości Wymagań RBT
zawierają:
TESTER.PL
Strona 14 z 63
• Walidacja wymagań w odniesieniu do celów biznesowych - optymalizacja zakresu
projektu przez zapewnianie, Ŝe kaŜde wymaganie zaspokaja przynajmniej jeden
biznesowy cel. JeŜeli brakuje powiązań pomiędzy wymaganiami a celami biznesowymi,
konieczna jest weryfikacja tych pierwszych.
• Przegląd wymagań przez uŜytkowników - zmiany dokonywane w wymaganiach powinny
być przeglądane i akceptowane przez uŜytkowników i odbiorców końcowych. W ten
sposób upewnimy się, Ŝe dodatkowa praca wynikająca z modyfikacji wymagań nie
będzie zmarnowana.
• Tworzenie przypadków uŜycia - kaŜdy przypadek uŜycia powinien być powiązany z
odpowiednim wymaganiem. Jeśli któryś z przypadków uŜycia nie ma takiego
przyporządkowania oznacza, Ŝe wymagania są niekompletne.
• Wykorzystanie technik analizy języka - wyszukiwanie i poprawianie problematycznych
wyraŜeń / sformułowań w opisie wymagań, pozwala na uniknięcie ich wieloznaczności i
niejasności oraz wyeliminowanie pomyłek. Pozostawienie takich fraz bez poprawy
powoduje iŜ mogą być one w późniejszych krokach interpretowane w róŜny sposób przez
róŜne osoby, co z kolei moŜe prowadzić do zakłopotania i błędów w kolejnych etapach.
Dwuznaczne określenia produkują równieŜ „nietestowalne” przypadki uŜycia.
2. Testujmy z głową, nie instynktownie
Większość przedsiębiorstw ceni doświadczonych testerów, licząc, Ŝe „wyłapią” błędy które inni,
mniej doświadczeni testerzy mogliby przeoczyć. O ile jednak pojedynczy „ekspert ds. jakości”
moŜe być kuszącym ograniczeniem kosztów firmy, o tyle sytuacja taka zwiększa ryzyko
polegania na instynkcie jednej osoby zamiast na grupowym racjonalnym podejściu.
Obecnie systematyczne i rygorystyczne planowanie przypadków testowych nie jest powszechnie
stosowaną praktyką. Częściej spotykamy się raczej z podejściem bardziej intuicyjnym,
polegającym na wyczuciu, co jednak w efekcie moŜe prowadzić do nieprzewidywalnej jakości
produktów końcowych. Doświadczenia firm stosujących podejście bazujące na RBT wskazują na
fakt, Ŝe stosowanie metodycznego i systematycznego projektowania przypadków testowych jest
najefektywniejszą polityką w zakresie jakości, zwłaszcza w perspektywie rozwoju firmy.
Rygorystyczne i systematyczne zasady projektowania przypadków testowych uniezaleŜniają
TESTER.PL
Strona 15 z 63
proces kontroli jakości od konkretnych testerów. W zamian wnoszą metodyczną powtarzalność
do procesu planowania testów, zapewniając tym samym przewidywalną powtarzalność pokrycia
testami. Organizacje bazujące na tej metodzie duŜo łatwiej mogą wprowadzać techniki
optymalizacji procesu testowania, redukując przypadki testowe do liczby efektywnie
pokrywającej wymagania, dzięki czemu uzyskują przyspieszenie cyklu testowego oraz utrzymują
ten proces na poziomie ułatwiającym zarządzanie nim.
W większości organizacji niemal wszyscy analitycy biznesowi uŜywają „naturalnego” języka do
opisu wymagań. Wiemy, iŜ uŜywanie takiego języka moŜe utrudnić osiągnięcie pełnego pokrycia
aplikacji testami, poniewaŜ testerzy bazując na potocznie sformułowanych wymaganiach muszą
odwoływać się do własnej intuicji, aby określić stopień pokrycia testami obszaru tak
zdefiniowanych wymagań. Innymi słowy, pracując z potocznie sformułowanymi wymaganiami
organizacje nie mają moŜliwości dokładnej kontroli pokrycia ich przypadkami testowymi, co
skutkuje w późniejszych błędach w wypuszczonej wersji aplikacji.
W celu usystematyzowania pokrycia wymagań odpowiadającymi im testami firmy i działy
produkujące oprogramowanie powinny skupić się na sformalizowaniu reprezentacji wymagań.
Kiedy uda się to osiągnąć, będzie moŜliwe stworzenie szkieletu przypadków testowych
zapewniających optymalne pokrycie wymagać, docelowo zaś powstaną z nich juŜ właściwe
testy, które będziemy mogli uruchamiać i przeprowadzać.
Aby wprowadzić usystematyzowanie i odpowiednią strukturę do wymagań sformułowanych przy
pomocy naturalnego języka opisu moŜna skorzystać z wielu dostępnych technik. Ich celem jest
odkrycie związków przyczynowo-skutkowych zawartych w wymaganiach, a przez to
przedstawienie ich w postaci zestawu warunków (przyczyn) oraz wynikających z nich akcji
(skutków). Tabele przyczynowo skutkowe są jedną z takich technik. Innym sposobem na
osiągnięcie podobnego rezultatu jest przedstawienie wymagań w postaci wykresów przepływu
(flowchart), które w naturalny sposób pokazują związki przyczynowo-skutkowe, jak równieŜ
gałęzie warunkowe odpowiednich akcji.
To swoiste „tłumaczenie” wymagań pozwala na duŜo łatwiejsze zbudowanie w oparciu o nie
konkretnych przypadków testowych. Logiczny zestaw tych ostatnich moŜe być stworzony
automatycznie bądź „ręcznie” tak, by stanowił odbicie zdefiniowanych i przetłumaczonych w
powyŜszy sposób wymagań. NaleŜy pamiętać, Ŝe tak stworzony zestaw przypadków testowych
moŜe zawierać nachodzące na siebie testy. W celu zoptymalizowania ich liczby przy zachowaniu
TESTER.PL
Strona 16 z 63
pełnego pokrycia wymagań moŜemy skorzystać z tablic decyzyjnych (w przypadku zastosowania
tabel przyczynowo-skutkowych na etapie strukturyzowania wymagań). W przypadku, jeśli w tym
celu opracowane zostały uprzednio wykresy zamiast tabel, optymalizacja sprowadza się do
znalezienia unikatowych ścieŜek przepływu na wykresach. Do tego celu moŜna wykorzystać
wiele sprawdzonych algorytmów.
Nawet po zaprojektowaniu przypadków testowych, wciąŜ będziemy mieli do czynienia z
prawdopodobieństwem występowania w nich błędów. Aby wykryć potencjalne błędy,
organizacje stosujące podejście RBT angaŜują zarówno analityków jak i uŜytkowników
końcowych do weryfikacji przypadków testowych zanim powstaną na ich podstawie właściwe
testy. To podejście pozwala wszystkim zainteresowanym ponownie zapoznać się z wymaganiami
i przypadkami testowymi, co daje moŜliwość ich dokładniejszej weryfikacji, jak równieŜ
wyłapania błędów powstałych w procesie przenoszenia wymagań z języka opisowego na
systematyczny.
Dodatkowo, firmy charakteryzujące się podejściem do cyklu tworzenia aplikacji jako całości,
starają się interaktywnie włączyć zadania Działu Jakości w prace analityków i programistów, co
staje się moŜliwe właśnie dzięki przejściu na usystematyzowane i zoptymalizowane przypadki
testowe wypracowane w poprzednich fazach.
W opisanym przedsiębiorstwie projekt aplikacji bywa przeglądany pod kątem przypadków
testowych, poniewaŜ stanowią one niejako inną formę zdefiniowanych wymagań. W ten sposób
zespoły projektowe nabierają pewności, Ŝe projekt spełnia załoŜenia i oczekiwania w postaci
wymagań. JeŜeli model ich nie spełnia moŜe to być oznaką, Ŝe albo nie odpowiada tymŜe, i
wymaga dalszej pracy, albo Ŝe jest problem w samych wymaganiach, co pociąga za sobą
dodatkową pracę analityków.
Aby uniknąć kosztownych przeróbek, przypadki testowe powinny być przeglądane równieŜ przez
programistów tworzących kod. To zapewni im dobre zrozumienie, które elementy oraz w jakim
zakresie będą testowane, a jednocześnie da strukturalny zestaw wymagań.
Ostatecznie pojedyncze moduły kodu powinny zostać zweryfikowane pod kątem
uporządkowanych wymagań tak, aby upewnić się, Ŝe powstały kod w pełni odpowiada
załoŜeniom. Praktyka pokazuje, Ŝe duŜo łatwiej jest nam dopasować postać algorytmiczną kodu
do uporządkowanych wymagań niŜ do ich niestrukturalnej postaci.
TESTER.PL
Strona 17 z 63
3. Nie zapominajmy o miarach i usprawnieniach
Istnieje opinia, Ŝe czego nie da się zmierzyć, nie istnieje. UŜywając metody RBT firmy mogą nie
tylko zarządzać procesem zarządzania jakością, ale i go usprawniać. W procesie RBT moŜe być
stosowanych wiele róŜnych miar kwantyfikujących status projektu oraz aktywność jego
członków. Stanowi to duŜą pomoc dla menedŜerów działu oraz menedŜerów projektu,
pozwalając na dokładny wgląd w zakres całego portfolio IT.
Przykłady informacji, które powinny być mierzone:
procent wymagań przejrzanych przez projektantów i programistów
procent wymagań, które zawierają dwuznaczności
procent wymagań o strukturalnej formie
procent formalnych wymagań pokrytych przypadkami testowymi
logiczne i faktyczne pokrycie kodu
Rola śledzenia zmian w RBT
Śledzenie zmian odgrywa takŜe istotną rolę w organizacjach wykorzystujących RBT - od
podtrzymywania stałego przepływu informacji o zmianach w stosunku do wymagań,
przypadków testowych i testów jest krytyczne. Te informacje są niezbędne dla prawidłowego
monitorowania postępu i stanu projektu, jak równieŜ do właściwego zarządzania zmianami
wymagań. Bez tej wiedzy trudne jest dokładne określenie, które przypadki testowe i testy
powinny zostać zmodyfikowane w przypadku zmiany w wymaganiach.
Nawet jeśli rozumiemy znaczenie śledzenia zmian, w wielu firmach tworzących oprogramowanie
ta wiedza wciąŜ pozostaje bardzo trudna do uchwycenia we właściwy sposób. Podstawowym
powodem tego jest to, Ŝe większość narzędzi dostępnych obecnie na rynku wymaga od niemal
wszystkich członków zespołów projektowych ręcznego wprowadzania i zarządzania śledzeniem
zmian. Z oczywistych powodów takie podejście jest raczej niemoŜliwe do zaakceptowania. Aby
podołać temu wyzwaniu, naleŜy powaŜnie zastanowić się nad rozwiązaniami umoŜliwiającymi
połączenia pomiędzy produktami poszczególnych faz wytwarzania oprogramowania.
Pierwszy krok do Zarządzania Jakością Cyklu śycia Aplikacji
Stosowanie solidnych praktyk RBT przez organizacje tworzące oprogramowanie bardzo szybko
dostarcza im odpowiednie narzędzia i procesy umoŜliwiające maksymalizację wartości
biznesowej działalności.
TESTER.PL
Strona 18 z 63
Zespoły wdraŜające podejście RBT poprzez fakt, Ŝe robią ten pierwszy krok w celu zwiększenia
jakości tworzonych produktów, stają się tym samym inicjatorami szeregu zmian prowadzących
do implementacji Zarządzania Jakością w Cyklu śycia Aplikacji (Lifecycle Quality Management –
LQM). Poprzez połoŜenie nacisku na zapewnienie jakości na wszystkich etapach wytwarzania
oprogramowania, a nie koncentrowanie się na jakości samego kodu, działania z obszaru LQM
zapewniają firmom podniesienie norm jakości i usług oraz systematyczną redukcję kosztów
związanych z wielokrotnym powtarzaniem tej samej pracy lub prób opanowania złoŜonych
projektów.
Ponadto, działania LQM znacząco przyspieszą ścieŜkę do Optymalizacji Procesu Dostarczania
Oprogramowania (Software Delivery Optimization - SDO), która z kolei pomaga przekształcić
tworzenie i rozwój oprogramowania w zarządzalny proces biznesowy, zapewniając tym samym
zwiększoną kontrolę, przewidywalność oraz wydajność w całym procesie dostarczania
oprogramowania.
TESTER.PL
Strona 19 z 63
Obiekt pozorny. A mo Ŝe coś innego ?
Kierunek rozwoju testów jednostkowych
Mateusz Bukowski i Paweł Paterek
Mateusz Bukowski jest absolwentem Akademii Górniczo Hutniczej w Krakowie, kierunku Informatyka na Wydziale Elektrotechniki, Automatyki, Informatyki i Elektroniki. Obecnie jest pracownikiem Motorola Polska Electronics Sp. z o.o. gdzie zajmuje się testowaniem systemu bezpieczeństwa publicznego TETRA. Jego zainteresowania to Ŝeglarstwo, cross country i rozwiązywanie łamigłówek logicznych.
Paweł Paterek jest absolwentem Wydziału Elektrotechniki, Automatyki, Informatyki i Elektroniki Akademii Górniczo-Hutniczej w Krakowie, kierunek Elektronika i Telekomunikacja. Obecnie jest pracownikiem firmy Motorola Polska Electronics Sp. z o.o., w której zajmuje się testowaniem oprogramowania systemów czasu rzeczywistego oraz systemów wbudowanych dla stacji bazowych w standardzie TETRA. Jego dziedziną zainteresowań jest modelowanie i ocena efektywności pracy sieci komputerowych.
TESTER.PL
Strona 20 z 63
Obiekt pozorny. A mo Ŝe coś innego ?
Kierunek rozwoju testów jednostkowych
Mateusz Bukowski i Paweł Paterek
W dzisiejszym świecie, dostarczenie produktu na czas, nie jest juŜ najwaŜniejszym
celem. DuŜo większe znaczenie, zaczyna odgrywać jakość dostarczanego oprogramowania.
PoniewaŜ testowanie zabiera coraz więcej czasu i wysiłku, niezbędne jest uproszczenie technik
testerskich przy jednoczesnym zachowaniu poziomu znajdowanych defektów. W tym artykule
zapoznamy się z obiektami pozornymi i zaślepkami, które wnoszą nową jakość do testów oraz
pokaŜemy, dlaczego warto korzystać z tych pierwszych.
Zanim przedstawimy nowe sposoby testowania, przypomnijmy, czego dotyczą testy
jednostkowe oraz czym jest programowanie sterowane testami.
Test jednostkowy (Unit test) to procedura mająca na celu walidację poprawności
działania danej jednostki kodu źródłowego. Przez jednostkę kodu źródłowego rozumiemy
najmniejszą i moŜliwą do przetestowania część oprogramowania. W programowaniu obiektowym
(ang. Object Oriented Programming) taką jednostkę kodu stanowi klasa [8]. Testy jednostkowe
odgrywają znaczącą rolę w procesie wytwarzania oprogramowania. UmoŜliwiają one wykrycie
wielu błędów w kodzie juŜ na etapie implementacji lub we wstępnej fazie testów. Pisane są
najczęściej przez te same osoby, które zajmują się tworzeniem danego fragmentu
oprogramowania.
Testy jednostkowe z załoŜenia są proste i szybkie w uruchomieniu. Testują
wyodrębnioną część funkcjonalności w całkowitej izolacji od reszty systemu. Pozwala to na
zautomatyzowanie znaczącej części procesu testowania. Tym samym pozwala to na częste
sprawdzanie czy wprowadzane zmiany w istniejącym kodzie nie powodują błędów.
Testy jednostkowe nie weryfikują wszystkich wymagań funkcjonalnych danego systemu.
Jest to zadanie testów akceptacyjnych wykonywanych przez odbiorcę oprogramowania [4],[10].
Ten rodzaj testów nie ma za zadania sprawdzać interakcji między róŜnymi obiektami, co wynika
wprost z ich definicji. Nie mogą wobec tego zastąpić testów integracyjnych i systemowych w
procesie testowania. Są jednak ich bardzo dobrym uzupełnieniem.
TESTER.PL
Strona 21 z 63
Bardzo często testowane klasy posiadają powiązania do innych klas. Utworzenie
referencji do takich obiektów w środowisku testowym niejednokrotnie jest niemoŜliwe. Jednym z
rozwiązań tego problemu są właśnie obiekty zastępcze powszechnie zwane obiektami pozornymi
(mock). Są to specjalnie przygotowane przez nas implementacje interfejsów mogące zastąpić
problematyczne części kodu oraz ułatwić wykonanie testów.
Programowanie sterowane testami (Test Driven Develomnent TDD) zakłada, Ŝe
Ŝaden fragment oprogramowania nie powstanie zanim nie napiszemy do niego odpowiedniego
testu. Pisany kod musi spełnić wymagania testu, a następnie moŜna przeprowadzić na nim
odpowiedni refactoring1, który pozwoli na ustalenie ostatecznego nazewnictwa metod czy
obiektów. Stosowanie tej metodologii ma róŜne zalety, m.in. pisząc pełny zbiór testów przed
napisaniem właściwego kodu piszemy zarazem specyfikację jego działania, po czym sama
walidacja jest juŜ automatyczna. PoniewaŜ przed napisaniem kodu wszystkie testy kończą się
błędem, a w miarę jak nasz kod spełnia coraz więcej wymagań tych błędów jest mniej, to
otrzymujemy tym samym miarę, w jakim stopniu nasz kod realizuje załoŜenia projektowe
[6],[1].
TDD pozwala małymi krokami (poprzez napisanie najmniejszej części kodu, która
powoduje pomyślne przejście testu) na sukcesywne i skuteczne realizowanie danego projektu.
Jednocześnie tak napisany kod jest mniej skomplikowany, dostajemy wysokie pokrycie testami,
a odnajdywanie błędów staje się znacznie prostsze. Jednak, kiedy test dotyczy kodu
odwołującego się do baz danych, zdalnych obiektów lub połączeń sieciowych napisanie go moŜe
być bardzo problematyczne. Chcąc jednak być w zgodzie z koncepcją metodologii TDD i
testować równieŜ takie obiekty, musimy zastąpić obiekty, do których odwołuje się testowany
kod i zaimitować ich obecność w testowanym kodzie. Jednym z moŜliwych sposobów testowania
takiego kodu jest wykorzystanie wspomnianych wyŜej lekkich obiektów pozornych lub duŜo
cięŜszych zaślepek [11],[14].
W naszych rozwaŜaniach będziemy posługiwać się następującym przykładem. Mamy
bazę danych ksiąŜek. KaŜdy element opisany jest następującymi parametrami: autor, tytuł oraz
identyfikator. Ponadto w bazie przechowywana jest równieŜ liczba dostępnych egzemplarzy
kaŜdej ksiąŜki. Z bazą danych moŜemy połączyć się poprzez BookManager’a, z którego korzysta
BookClient.
TESTER.PL
Strona 22 z 63
public interface BookManager { public boolean connect(); public boolean disconnect(); public TreeMap<Book, Integer> bookList(); public boolean order(BookOrder bookOrder) throw s BookNotFoundException, NotEnoughBooksException; } public class BookClient { public static final String CONNECT_ERROR = "Dat abase connect error"; public static final String DISCONNECT_ERROR = " Database disconnect error"; public static final String BOOK_NOT_FOUND_ERROR = "Book not found error"; public static final String NOT_ENOUGH_BOOKS_ERR OR = "Not enough books error"; public static final String AVAILABLE_BOOKS = "A vailable books:"; public static final String ORDERED_BOOKS = "Ord ered books:"; public static final String BOOK_ORDER_FAIL = "B ook order failed error"; private BookManager bookManager; private String message; public BookClient() { bookManager = new DefaultBookManager(); message = ""; } public BookClient(BookManager bookManager) { this.bookManager = bookManager; message = ""; } public String getMessage() {
Rys. 1 Schemat systemu zamawiania ksiąŜek
TESTER.PL
Strona 23 z 63
return message; } public void getBookList() { if (!bookManager.connect()) { message = CONNECT_ERROR; return; } message = AVAILABLE_BOOKS + bookListToStrin g(bookManager.bookList()); if (!bookManager.disconnect()) { message = DISCONNECT_ERROR; return; } } public void orderBooks(BookOrder bookOrder) { if (!bookManager.connect()) { message = CONNECT_ERROR; return; } try { if (bookManager.order(bookOrder)) { message = ORDERED_BOOKS + bookListToString(bookOrder.getBookList()); } else { message = BOOK_ORDER_FAIL; } } catch (BookNotFoundException e) { message = BOOK_NOT_FOUND_ERROR; } catch (NotEnoughBooksException e) { message = NOT_ENOUGH_BOOKS_ERROR; } if (!bookManager.disconnect()) { message = DISCONNECT_ERROR; return; } } public static String bookListToString(TreeMap<B ook, Integer> bookList) { StringBuilder result; result = new StringBuilder(); for (Book book: bookList.keySet()) { result.append("\n"); result.append(book.getId()); result.append(" "); result.append(book.getAuthor()); result.append(" "); result.append(book.getTitle()); result.append(" "); result.append(bookList.get(book)); } return result.toString(); }
TESTER.PL
Strona 24 z 63
}
Implementacja pozostałych klas: Book, BookOrder, DefaultBookManager,
NotEnoughBooksException oraz BookNotFoundException nie jest istotna w naszych
rozwaŜaniach. Niezbędna jest implementacja funkcji equals, hashCode oraz compareTo w klasie
Book, poniewaŜ będziemy uŜywać tych obiektów jako kluczy w TreeMap’ie.
Testowaną klasą jest BookClient. BookManager jest interfejsem, który będą
implementować konkretne obiekty. Domyślnie jest to klasa DefaultBookManager. Na potrzeby
testów dodaliśmy drugi konstruktor, w którym przekazujemy specjalnie spreparowany
BookManager. Inną stosowaną praktyką jest równieŜ korzystanie z metod ‘set’.
Wspomniane wcześniej obiekty pozorne nie są jedyną moŜliwością na zastąpienie
prawdziwych obiektów w obiekcie testowanym. Często teŜ bywają mylone z podobnymi do nich
w zastosowaniu, lecz róŜniącymi się funkcjonalnie obiektami atrapami (ang. dummy
objects), obiektami falsyfikatami (ang. fake objects) oraz zaślepkami (ang. stubs).
Obiekty atrapy przekazywane są do obiektu testowanego, ale nigdzie nie są uŜywane i
zazwyczaj słuŜą jedynie do wypełnienia listy parametrów testowanej metody.
Falsyfikaty (w Ŝargonie informatycznym często nazywane fake’ami) posiadają
namiastkę działającej implementacji, najczęściej stworzoną ręcznie w ramach kodu testów (na
przykład w postaci klasy anonimowej). Implementacja ta jest zazwyczaj skrócona do minimum,
co sprawia, Ŝe nie nadają się one do uŜycia w prawdziwym kodzie. Wadami falsyfikatów są: czas
poświęcony na ich stworzenie, zwiększenie zawartości całego projektu, a takŜe konieczność ich
utrzymywania, w trakcie zmiany interfejsów kodu, z których one korzystają.
Zaślepki mogą być napisane ręcznie lub generowane automatycznie i są najczęściej
stosowane wtedy, gdy kod nie jest znany, nie jest gotowy na etapie testowania danego obiektu
lub, gdy nie ma moŜliwości dostępu do danej części kodu, co czasami znacznie ułatwia i
przyspiesza proces tworzenia oprogramowania [2], [5]. Zaślepki symulują zachowanie
prawdziwego kodu. W naszym przykładzie będzie łączył się z prawdziwą bazą danych. Innym
razem w celu dogłębnego przetestowania z uŜyciem tej techniki musielibyśmy uruchomić serwer
http. Zaślepki są bardzo kosztowne w utrzymaniu. Jeśli są stosowane we wczesnych fazach
testowania mogą później słuŜyć jako zaląŜki dla implementacji prawdziwych klas.
Obiektami pozornymi zajmiemy się dokładniej w dalszej części.
Implementacja BookManager’a moŜe być jednym z powyŜszych typów: falsyfikat,
zaślepka, obiekt pozorny.
Przyjrzyjmy się teraz konkretnym falsyfikatom i zaślepkom oraz odpowiadającym im
testom jednostkowym.
TESTER.PL
Strona 25 z 63
public class FakeBookManager implements BookManager { private TreeMap<Book, Integer> bookList; private int call; public FakeBookManager() { bookList = new TreeMap<Book, Integer>(); bookList.put(new Book(101, "Ernest Hemingwa y", "The Old Man and the Sea"), 3); bookList.put(new Book(102, "Gabriel Garcia Marquez", "One Hundred Years of Solitude"), 5); bookList.put(new Book(103, "Joanne Kathleen Rowling", "Harry Potter and the Deathly Hallows"), 27); call = 0; } public boolean connect() { return true; } public boolean disconnect() { return true; } public TreeMap<Book, Integer> bookList() { return bookList; } public boolean order(BookOrder bookOrder) throw s BookNotFoundException, NotEnoughBooksException { call++; switch (call % 8) { case 0: case 2: case 4: return true; case 1: case 3: case 5: return false; case 6: throw new BookNotFoundException(); case 7: throw new NotEnoughBooksException() ; default: return true; } } }
TESTER.PL
Strona 26 z 63
Jak widzimy nasz falsyfikat ma zaszytą namiastkę logiki. Wiedząc, który raz wywołujemy metodę
order(), moŜemy sprawdzić czy BookClient zachowuje się w poprawny sposób.
public class BookClientTestFakeBookManager extends TestCase { private TreeMap<Book, Integer> bookList; private static final Book QUO_VADIS = new Book( 1001, "Henryk Sienkiewicz", "Quo Vadis"); private static final Book PAN_TADEUSZ = new Boo k(2001, "Adam Mickiewicz", "Pan Tadeusz"); private static final Book CHLOPI = new Book(300 1, "Wladyslaw Reymont", "Chlopi"); @Override protected void setUp() throws Exception { super.setUp(); bookList = new TreeMap<Book, Integer>(); bookList.put(QUO_VADIS, 2); bookList.put(PAN_TADEUSZ, 3); bookList.put(CHLOPI, 5); } public void testOrderGlobal() { BookClient client; FakeBookManager fake; BookOrder bookOrder; String message; fake = new FakeBookManager(); client = new BookClient(fake); bookOrder = new BookOrder(); bookOrder.addBook(CHLOPI); client.orderBooks(bookOrder); message = BookClient.BOOK_ORDER_FAIL; assertEquals(message, client.getMessage()); client.orderBooks(bookOrder); message = BookClient.ORDERED_BOOKS + BookClient.bookListToString(bookOrder.getBookList() ); assertEquals(message, client.getMessage()); client.orderBooks(bookOrder); client.orderBooks(bookOrder); client.orderBooks(bookOrder); client.orderBooks(bookOrder); message = BookClient.BOOK_NOT_FOUND_ERROR; assertEquals(message, client.getMessage()); client.orderBooks(bookOrder); message = BookClient.NOT_ENOUGH_BOOKS_ERROR ; assertEquals(message, client.getMessage());
TESTER.PL
Strona 27 z 63
} }
W przykładzie z zaślepką uŜyliśmy najprostszego rozwiązania. Jako bazy danych uŜyliśmy
Accessa. UŜywanie tej aplikacji nie wymaga obszernej wiedzy z zakresu zarządzania bazami
danych. Access jest łatwy do konfiguracji, prosty w obsłudze i świetnie nadaje się do celów
testowych. Gdybyśmy chcieli symulować serwer http nie musimy mieć postawionego Apache’a.
MoŜemy uŜyć prostego symulatora Jetty, który jest prostą aplikacją javową.
public class StubBookManager implements BookManager { private Connection conn; private String url; private String username; private String password; public StubBookManager(String location) { url = "jdbc:odbc:Driver={Microsoft Access D river (*.mdb)};DBQ=" + location; username = ""; password = ""; } public boolean connect() { try { Class.forName("sun.jdbc.odbc.JdbcOdbcDr iver"); conn = DriverManager.getConnection(url, username, password); } catch (ClassNotFoundException e) { return false; } catch (SQLException e) { return false; } return true; } public boolean disconnect() { try { conn.close(); } catch (SQLException e) { return false; } return true; } public TreeMap<Book, Integer> bookList() { TreeMap<Book, Integer> result; Statement st; ResultSet rs; Book book; int quantity;
TESTER.PL
Strona 28 z 63
result = new TreeMap<Book, Integer>(); try { st = conn.createStatement(); rs = st.executeQuery("SELECT * FROM boo ks"); while (rs.next()) { book = new Book(rs.getInt("id"), rs .getString("author"), rs.getString("title")); quantity = rs.getInt("quantity"); result.put(book, quantity); } } catch (SQLException e) { return new TreeMap<Book, Integer>(); } return result; } public synchronized boolean order(BookOrder boo kOrder) throws BookNotFoundException, NotEnoughBooksException { TreeMap<Book, Integer> bookList; Statement st; int quantity; bookList = bookList(); for (Book book: bookOrder.getBookList().key Set()) { if (!bookList.containsKey(book)) { throw new BookNotFoundException(); } quantity = bookList.get(book) - bookOrd er.getBookList().get(book); if (quantity < 0) { throw new NotEnoughBooksException() ; } try { st = conn.createStatement(); st.executeUpdate( "UPDATE books" + " SET quantity = " + quanti ty + " WHERE id = " + book.getId () + " AND author = '" + book.ge tAuthor() + "'" + " AND title = '" + book.get Title() + "'"); } catch (SQLException e) { return false; } } return true; } }
Do poprawnego uruchomienia poniŜszego testu konieczne jest dodanie katalogu ‘data’ z
odpowiednią plikiem bazy danych ‘book.mdb’.
TESTER.PL
Strona 29 z 63
public class BookClientTestStubBookManager extends TestCase { public void testConnectOk() { BookClient client; StubBookManager stub; String message; stub = new StubBookManager("./data/book.mdb "); client = new BookClient(stub); client.getBookList(); message = BookClient.AVAILABLE_BOOKS; assertEquals(message, client.getMessage()); } public void testConnectFail() { BookClient client; StubBookManager stub; String message; stub = new StubBookManager("dummy.mdb"); client = new BookClient(stub); client.getBookList(); message = BookClient.CONNECT_ERROR; assertEquals(message, client.getMessage()); } }
Obiekt pozorny (mock) jest imitacją stworzoną na potrzeby testu jednostkowego w
celu sprawdzenia poprawności współpracy testowanego obiektu z jego najbliŜszym otoczeniem
[9]. Bardziej formalne interpretacje tego pojęcia to:
a) obiekt pozorny jest pewną atrapą zastępującą prawdziwy obiekt, który jest niedostępny
lub trudny do uŜycia w scenariuszu testowym
b) obiekt pozorny musi posiadać mechanizm do automatycznej walidacji ustawionych dla
niego wcześniej oczekiwanych zachowań [4],[10].
Obiekty te powinny zawsze zwracać z góry określone dane, umoŜliwiając testowanie logiki
aplikacji w jednoznaczny sposób, bez konieczności odwoływania się do prawdziwych obiektów,
bądź baz danych. Ich logika oraz implementacja powinna być najprostsza jak to tylko moŜliwe
oraz niezaleŜna od innych obiektów pozornych, bądź fragmentów testowanej aplikacji.
Mechanizm automatycznej walidacji powinien zadziałać w momencie wystąpienia błędu,
umoŜliwiając szybkie przerwanie testu i łatwą lokalizację przyczyny problemu [4],[9].
TESTER.PL
Strona 30 z 63
Program zorientowany obiektowo jest siecią obiektów
wzajemnie ze sobą współpracujących. Aby dobrze
przetestować działanie obiektu, naleŜy przetestować
poprawność jego współpracy z obiektami, z którymi wymienia
informacje w prawdziwej aplikacji. PoniewaŜ unit test polega
na testowaniu obiektu w izolacji od innych obiektów
istniejących w aplikacji, obiekty wymieniające informacje z
obiektem testowanym muszą zostać podmienione na obiekty
pozorne, patrz rys. 2 [6]. W chwili, kiedy na obiekcie
zastępczym wystąpi inne wywołanie metody niŜ oczekiwane,
lub wywołanie nastąpi z niewłaściwymi parametrami lub teŜ, gdy wywołanie wystąpi, a nie było
ono jawnie oczekiwane test jest automatycznie przerywany i jego wynik ustawiany jest na
negatywny [7].
Powody, dla których uŜycie obiektów pozornych moŜe być nieocenione, są przeróŜne.
Prawdziwy obiekt wykazuje zachowanie niedeterministyczne. Jest trudno konfigurowalny. Jego
działanie jest znacznie wolniejsze (niepotrzebnie wydłuŜając test). Część jego zdarzeń jest
trudna do wywołania (szczególnie sytuacje dotyczące występowania błędów). Prawdziwy obiekt
moŜe mieć lub stanowić interfejs uŜytkownika. NajwaŜniejsze jest to, Ŝe prawdziwy obiekt moŜe
jeszcze nie być w ogóle stworzony lub test moŜe chcieć wywołać na nim specyficzne zapytanie,
które nie jest dostępne w prawdziwym obiekcie w danej chwili [13],[10].
Korzystanie z obiektów pozornych posiada charakterystyczny wzorzec, który moŜna
stosować podczas tworzenia testów. Najpierw tworzymy instancję obiektu pozornego, następnie
ustawiamy ich stan (parametry i atrybuty uŜywane przez testowany obiekt), a na koniec
ustawiamy ich oczekiwane zachowania (oraz ewentualne wartości zwracane), które powinny być
wywołane przez testowany obiekt. Testowany kod wywołujemy podając jako parametry
wcześniej przygotowane obiekty zastępcze i sprawdzamy czy wszystkie wywołania, które się do
nich odnoszą są zgodne z naszymi oczekiwaniami [3].
Praktycznym ułatwieniem stosowania tej techniki moŜe być stworzenie interfejsu
opisującego dany obiekt, a następnie implementacja tego interfejsu zarówno dla kodu, jak i w
celu stworzenia obiektu zastępczego uŜywanego podczas testu. Jednym z typowych przykładów
zastosowania techniki obiektów pozornych, moŜe być testowanie logiki biznesowej, odwołującej
się do zdalnej bazy danych (rys. 3). Sterownik bazy danych implementuje najczęściej
standardowy interfejs dostępu do bazy danych. Ten sam interfejs moŜna uŜyć do stworzenia
obiektu pozornego, dzięki czemu nie musimy mieć dostępu do prawdziwej bazy danych.
Rys. 2 Wymiana informacji Test – Obiekt – Obiekt Pozorny
TESTER.PL
Strona 31 z 63
Ze względu na sposób tworzenia (uŜytą technikę
programowania) obiektów pozornych moŜna podzielić na dwa
rodzaje: obiektów pozornych statycznych oraz obiektów
pozornych dynamicznych. Obiekty pozorne statyczne moŜemy
tworzyć na dwa róŜne sposoby, poprzez zwykłą ręczną
implementację dodatkowej klasy lub moŜna je wygenerować
automatycznie (na etapie kompilacji bądź uruchomienia kodu
testu). Obiekty pozorne dynamiczne równieŜ moŜna tworzyć na
dwa sposoby: za pomocą interfejsu zwanego proxy lub za pomocą bardziej zaawansowanych
technik programistycznych. Obiekty pozorne statyczne moŜemy uŜyć w przypadku pojedynczych
testów, bądź niewielkich i niezbyt skomplikowanych projektów, natomiast w przypadku duŜych
projektów (duŜa liczba klas, które musielibyśmy napisać w przypadku pozorantów statycznych),
gdzie najczęściej podmieniane obiekty mają rozbudowane funkcjonalności bardziej odpowiednie
staje się uŜycie obiektów pozornych dynamicznych [12].
W odróŜnieniu od technik opisanych powyŜej obiekty pozorne są najczęściej
automatycznie generowanymi obiektami zastępczymi z zaprogramowanymi wcześniej
oczekiwaniami wywołań z obiektu testowanego, które są jednocześnie specyfikacją zachowań
tego obiektu. Obiekty te mogą zapisywać wykonane wywołania z obiektu testowanego w celu
porównania tej informacji z oczekiwaniami wynikającymi ze scenariusza testu. Z wszystkich
wymienionych technik tylko obiekty zastępcze weryfikują zachowanie testowanego obiektu, a
pozostałe weryfikują jedynie stany, w których znajduje się testowany obiekt [5]. Obiekty
pozorne są najczęściej generowani dynamicznie w trakcie uruchamiania testów, a więc nie ma
potrzeby tworzenia dodatkowych klas z kodem, a zarazem utrzymywania i aktualizacji ich kodu,
co znacznie odróŜnia je od pozostałych technik. Całość logiki obiektów zastępczych, a więc zbiór
oczekiwanych zachowań jest trzymany razem z kodem testów [2].
Wszystkie przedstawione powyŜej techniki mają teŜ wspólne cechy, takie jak: moŜliwość
eliminacji wielu zaleŜności w kodzie, inaczej mówiąc moŜliwość testowania wybranych
fragmentów kodu w izolacji, czyli bez środowiska, w którym ten kod pracuje, moŜliwość
testowania scenariuszy hipotetycznych lub rzadko występujących w prawdziwym działaniu kodu,
moŜliwość znacznego przyspieszenia samego procesu testowania, pozwalając tym samym na
częste uruchamianie testów jednostkowych, a jednocześnie na realizację idei testów
jednostkowych.
PoniŜej przedstawiamy róŜne podejścia do obiektów pozornych. Na początek obiekt pozorny
napisany od początku do końca przez nas.
Rys. 3 Przykład zastosowania obiektu pozornego
TESTER.PL
Strona 32 z 63
public class MyMockBookManager implements BookManag er { private TreeMap<Book, Integer> bookList; private boolean connect; private boolean disconnect; private int expectedOrderCount; private int orderCount; private int expectedConnectCount; private int connectCount; private int expectedDisconnectCount; private int disconnectCount; public MyMockBookManager() { bookList = new TreeMap<Book, Integer>(); connect = false; disconnect = false; expectedOrderCount = 0; expectedConnectCount = 0; expectedDisconnectCount = 0; orderCount = 0; connectCount = 0; disconnectCount = 0; } public boolean connect() { connectCount++; return connect; } public boolean disconnect() { disconnectCount++; return disconnect; } public TreeMap<Book, Integer> bookList() { return bookList; } public boolean order(BookOrder bookOrder) throw s BookNotFoundException, NotEnoughBooksException { orderCount++; for (Book book: bookOrder.getBookList().key Set()) { if (!bookList.containsKey(book)) { throw new BookNotFoundException(); } if (bookList.get(book) < bookOrder.getB ookList().get(book)) { throw new NotEnoughBooksException() ;
TESTER.PL
Strona 33 z 63
} } return true; } public void setConnect(boolean connect) { this.connect = connect; } public void setDisconnect(boolean disconnect) { this.disconnect = disconnect; } public void setBookList(TreeMap<Book, Integer> bookList) { this.bookList = bookList; } public void setExpectedConnectCount(int expecte dConnectCount) { this.expectedConnectCount = expectedConnect Count; } public void setExpectedDisconnectCount(int expe ctedDisconnectCount) { this.expectedDisconnectCount = expectedDisc onnectCount; } public void setExpectedOrderCount(int expectedO rderCount) { this.expectedOrderCount = expectedOrderCoun t; } public void verify() { if (expectedOrderCount != orderCount) { Assert.fail("Wrong number of performed orders"); } if (expectedConnectCount != connectCount) { Assert.fail("Wrong number of performed connects"); } if (expectedDisconnectCount != disconnectCo unt) { Assert.fail("Wrong number of performed disconnects"); } } } public class BookClientTestMyMockBookManager extend s TestCase { private TreeMap<Book, Integer> bookList; private static final Book QUO_VADIS = new Book( 1001, "Henryk Sienkiewicz", "Quo Vadis"); private static final Book PAN_TADEUSZ = new Boo k(2001, "Adam Mickiewicz", "Pan Tadeusz"); private static final Book CHLOPI = new Book(300 1, "Wladyslaw Reymont", "Chlopi"); @Override
TESTER.PL
Strona 34 z 63
protected void setUp() throws Exception { super.setUp(); bookList = new TreeMap<Book, Integer>(); bookList.put(QUO_VADIS, 2); bookList.put(PAN_TADEUSZ, 3); bookList.put(CHLOPI, 5); } public void testOrderOk() { BookClient client; MyMockBookManager mock; BookOrder bookOrder; String message; mock = new MyMockBookManager(); mock.setBookList(bookList); mock.setConnect(true); mock.setDisconnect(true); mock.setExpectedConnectCount(1); mock.setExpectedDisconnectCount(1); mock.setExpectedOrderCount(1); client = new BookClient(mock); bookOrder = new BookOrder(); bookOrder.addBook(QUO_VADIS); bookOrder.addBook(PAN_TADEUSZ); client.orderBooks(bookOrder); message = BookClient.ORDERED_BOOKS + BookClient.bookListToString(bookOrder.getBookList() ); assertEquals(message, client.getMessage()); mock.verify(); } public void testOrderFail() { BookClient client; MyMockBookManager mock; BookOrder bookOrder; String message; mock = new MyMockBookManager(); mock.setBookList(bookList); mock.setConnect(true); mock.setDisconnect(true); mock.setExpectedConnectCount(1); mock.setExpectedDisconnectCount(1); mock.setExpectedOrderCount(1); client = new BookClient(mock); bookOrder = new BookOrder(); bookOrder.addBook(QUO_VADIS);
TESTER.PL
Strona 35 z 63
bookOrder.addBook(PAN_TADEUSZ); bookOrder.addBook(PAN_TADEUSZ); bookOrder.addBook(PAN_TADEUSZ); bookOrder.addBook(PAN_TADEUSZ); client.orderBooks(bookOrder); message = BookClient.NOT_ENOUGH_BOOKS_ERROR ; assertEquals(message, client.getMessage()); mock.verify(); } }
Jak łatwo zauwaŜyć klasa MyMockBookManager jest dość obszerna. Wyobraźmy sobie ile
musielibyśmy napisać takich klas w przypadku duŜego systemu. Na szczęście z pomocą
przychodzi nam MockMaker. Jest to biblioteka słuŜąca do generacji obiektów pozornych
z podanego interfejsu. Wygenerowany obiekt pozorny jest bardzo przyjazny dla uŜytkownika,
a testy z jego uŜyciem pisze się bardzo sprawnie. Co więcej moŜe on być włączony jako wtyczka
do eclipse’a. Więcej szczegółów moŜemy znaleźć na stronie domowej projektu
http://mockmaker.sourceforge.net/ oraz w [15].
public class MockBookManager implements BookManager { private ExpectationCounter myConnectCalls = new ExpectationCounter("example.book.BookManager Connec tCalls"); private ReturnValues myActualConnectReturnValues = new ReturnValues(false); private ExpectationCounter myDisconnectCalls = n ew ExpectationCounter("example.book.BookManager Discon nectCalls"); private ReturnValues myActualDisconnectReturnVal ues = new ReturnValues(false); private ExpectationCounter myBookListCalls = new ExpectationCounter("example.book.BookManager BookLi stCalls"); private ReturnValues myActualBookListReturnValue s = new ReturnValues(false); private ExpectationCounter myOrderCalls = new ExpectationCounter("example.book.BookManager OrderC alls"); private ReturnValues myActualOrderReturnValues = new ReturnValues(false); private ExpectationList myOrderParameter0Values = new ExpectationList("example.book.BookManager example.b ook.BookOrder"); public void setExpectedConnectCalls(int calls){ myConnectCalls.setExpected(calls); } public boolean connect(){ myConnectCalls.inc(); Object nextReturnValue = myActualConnectRetur nValues.getNext(); if (nextReturnValue instanceof ExceptionalRet urnValue && ((ExceptionalReturnValue)nextReturnValue).getExcept ion() instanceof RuntimeException) throw (RuntimeException)((ExceptionalReturnValue)nextRetu rnValue).getException(); return ((Boolean) nextReturnValue).booleanVal ue();
TESTER.PL
Strona 36 z 63
} public void setupExceptionConnect(Throwable arg) { myActualConnectReturnValues.add(new Exception alReturnValue(arg)); } public void setupConnect(boolean arg){ myActualConnectReturnValues.add(new Boolean(a rg)); } public void setExpectedDisconnectCalls(int calls ){ myDisconnectCalls.setExpected(calls); } public boolean disconnect(){ myDisconnectCalls.inc(); Object nextReturnValue = myActualDisconnectRe turnValues.getNext(); if (nextReturnValue instanceof ExceptionalRet urnValue && ((ExceptionalReturnValue)nextReturnValue).getExcept ion() instanceof RuntimeException) throw (RuntimeException)((ExceptionalReturnValue)nextRetu rnValue).getException(); return ((Boolean) nextReturnValue).booleanVal ue(); } public void setupExceptionDisconnect(Throwable a rg){ myActualDisconnectReturnValues.add(new Except ionalReturnValue(arg)); } public void setupDisconnect(boolean arg){ myActualDisconnectReturnValues.add(new Boolea n(arg)); } public void setExpectedBookListCalls(int calls){ myBookListCalls.setExpected(calls); } public TreeMap<Book,Integer> bookList(){ myBookListCalls.inc(); Object nextReturnValue = myActualBookListRetu rnValues.getNext(); if (nextReturnValue instanceof ExceptionalRet urnValue && ((ExceptionalReturnValue)nextReturnValue).getExcept ion() instanceof RuntimeException) throw (RuntimeException)((ExceptionalReturnValue)nextRetu rnValue).getException(); return (TreeMap<Book,Integer>) nextReturnValu e; } public void setupExceptionBookList(Throwable arg ){ myActualBookListReturnValues.add(new Exceptio nalReturnValue(arg)); } public void setupBookList(TreeMap<Book,Integer> arg){ myActualBookListReturnValues.add(arg); } public void setExpectedOrderCalls(int calls){ myOrderCalls.setExpected(calls); } public void addExpectedOrderValues(BookOrder arg 0){
TESTER.PL
Strona 37 z 63
myOrderParameter0Values.addExpected(arg0); } public boolean order(BookOrder arg0) throws Book NotFoundException, NotEnoughBooksException{ myOrderCalls.inc(); myOrderParameter0Values.addActual(arg0); Object nextReturnValue = myActualOrderReturnV alues.getNext(); if (nextReturnValue instanceof ExceptionalRet urnValue && ((ExceptionalReturnValue)nextReturnValue).getExcept ion() instanceof BookNotFoundException) throw (BookNotFoundException)((ExceptionalReturnValue)nex tReturnValue).getException(); if (nextReturnValue instanceof ExceptionalRet urnValue && ((ExceptionalReturnValue)nextReturnValue).getExcept ion() instanceof NotEnoughBooksException) throw (NotEnoughBooksException)((ExceptionalReturnValue)n extReturnValue).getException(); if (nextReturnValue instanceof ExceptionalRet urnValue && ((ExceptionalReturnValue)nextReturnValue).getExcept ion() instanceof RuntimeException) throw (RuntimeException)((ExceptionalReturnValue)nextRetu rnValue).getException(); return ((Boolean) nextReturnValue).booleanVal ue(); } public void setupExceptionOrder(Throwable arg){ myActualOrderReturnValues.add(new Exceptional ReturnValue(arg)); } public void setupOrder(boolean arg){ myActualOrderReturnValues.add(new Boolean(arg )); } public void verify(){ myConnectCalls.verify(); myDisconnectCalls.verify(); myBookListCalls.verify(); myOrderCalls.verify(); myOrderParameter0Values.verify(); } } public class BookClientTestMockBookManager extends TestCase { private TreeMap<Book, Integer> bookList; private static final Book QUO_VADIS = new Book( 1001, "Henryk Sienkiewicz", "Quo Vadis"); private static final Book PAN_TADEUSZ = new Boo k(2001, "Adam Mickiewicz", "Pan Tadeusz"); private static final Book CHLOPI = new Book(300 1, "Wladyslaw Reymont", "Chlopi"); private BookClient client;
TESTER.PL
Strona 38 z 63
private MockBookManager mock; @Override protected void setUp() throws Exception { super.setUp(); bookList = new TreeMap<Book, Integer>(); bookList.put(QUO_VADIS, 2); bookList.put(PAN_TADEUSZ, 3); mock = new MockBookManager(); client = new BookClient(mock); } public void testSecondConnectFail() { String message; BookOrder bookOrder; mock.setExpectedConnectCalls(2); mock.setExpectedDisconnectCalls(1); mock.setExpectedBookListCalls(1); mock.setExpectedOrderCalls(0); mock.setupConnect(true); mock.setupConnect(false); mock.setupDisconnect(true); mock.setupBookList(bookList); client.getBookList(); message = BookClient.AVAILABLE_BOOKS + BookClient.bookListToString(bookList); assertEquals(message, client.getMessage()); bookOrder = new BookOrder(); client.orderBooks(bookOrder); message = BookClient.CONNECT_ERROR; assertEquals(message, client.getMessage()); mock.verify(); } public void testSecondOrderFailWithBookNotFound Exception() { String message; BookOrder first; BookOrder second; first = new BookOrder(); first.addBook(QUO_VADIS); first.addBook(QUO_VADIS); second = new BookOrder(); second.addBook(CHLOPI); mock.setExpectedConnectCalls(2); mock.setExpectedDisconnectCalls(2); mock.setExpectedOrderCalls(2);
TESTER.PL
Strona 39 z 63
mock.setupConnect(true); mock.setupConnect(true); mock.setupDisconnect(true); mock.setupDisconnect(true); mock.setupBookList(bookList); mock.addExpectedOrderValues(first); mock.addExpectedOrderValues(second); mock.setupOrder(true); mock.setupExceptionOrder(new BookNotFoundEx ception()); client.orderBooks(first); message = BookClient.ORDERED_BOOKS + BookClient.bookListToString(first.getBookList()); assertEquals(message, client.getMessage()); client.orderBooks(second); message = BookClient.BOOK_NOT_FOUND_ERROR; assertEquals(message, client.getMessage()); mock.verify(); } }
Inne podejście do obiektów pozornych prezentują biblioteki takie jak EasyMock i jMock.
Tworzą one pewnego rodzaju proxy na podstawie przedstawionego interfejsu. Mechanizm
działania takiego testu wygląda w następujący sposób. Najpierw nagrywamy zachowanie
obiektu pozornego:
• jakie metody powinny być uruchomione i ile razy
• jakie wartości powinny być zwrócone lub rzucone wyjątki
Następnie uruchamiamy test i weryfikujemy zachowanie obiektu testowanego.
Na poniŜszych wydrukach kodu, te przedstawione metody są najbardziej ekonomiczne i
przyjazne w uŜyciu przez uŜytkownika.
public class BookClientTestEasyMock extends TestCa se { private TreeMap<Book, Integer> bookList; private static final Book QUO_VADIS = new Book( 1001, "Henryk Sienkiewicz", "Quo Vadis"); private static final Book PAN_TADEUSZ = new Boo k(2001, "Adam Mickiewicz", "Pan Tadeusz"); private static final Book CHLOPI = new Book(300 1, "Wladyslaw Reymont", "Chlopi");
TESTER.PL
Strona 40 z 63
private BookClient client; private BookManager mock; @Override protected void setUp() throws Exception { super.setUp(); bookList = new TreeMap<Book, Integer>(); bookList.put(QUO_VADIS, 2); bookList.put(PAN_TADEUSZ, 3); bookList.put(CHLOPI, 5); mock = EasyMock.createMock(BookManager.clas s); client = new BookClient(mock); } public void testBookList() { String message; EasyMock.expect(mock.connect()).andReturn(t rue); EasyMock.expect(mock.bookList()).andReturn( bookList); EasyMock.expect(mock.disconnect()).andRetur n(true); EasyMock.replay(mock); client.getBookList(); message = BookClient.AVAILABLE_BOOKS + BookClient.bookListToString(bookList); assertEquals(message, client.getMessage()); EasyMock.verify(mock); } public void testNotEnoughBooks() { String message; BookOrder bookOrder; bookOrder = new BookOrder(); bookOrder.addBook(QUO_VADIS); EasyMock.expect(mock.connect()).andReturn(t rue); EasyMock.expectLastCall().times(3); try { EasyMock.expect(mock.order(EasyMock.eq( bookOrder))). andReturn(true). andReturn(true). andThrow(new NotEnoughBooksExceptio n()); } catch (BookNotFoundException e) { } catch (NotEnoughBooksException e) { } EasyMock.expect(mock.disconnect()).andRetur n(true).times(3); EasyMock.replay(mock); client.orderBooks(bookOrder);
TESTER.PL
Strona 41 z 63
message = BookClient.ORDERED_BOOKS + BookClient.bookListToString(bookOrder.getBookList() ); assertEquals(message, client.getMessage()); client.orderBooks(bookOrder); message = BookClient.ORDERED_BOOKS + BookClient.bookListToString(bookOrder.getBookList() ); assertEquals(message, client.getMessage()); client.orderBooks(bookOrder); message = BookClient.NOT_ENOUGH_BOOKS_ERROR ; assertEquals(message, client.getMessage()); EasyMock.verify(mock); } } public class BookClientTestJMock extends TestCase { private TreeMap<Book, Integer> bookList; private static final Book QUO_VADIS = new Book( 1001, "Henryk Sienkiewicz", "Quo Vadis"); private static final Book PAN_TADEUSZ = new Boo k(2001, "Adam Mickiewicz", "Pan Tadeusz"); private static final Book CHLOPI = new Book(300 1, "Wladyslaw Reymont", "Chlopi"); private BookClient client; private BookManager mock; private Mockery context; @Override protected void setUp() throws Exception { super.setUp(); bookList = new TreeMap<Book, Integer>(); bookList.put(QUO_VADIS, 2); bookList.put(PAN_TADEUSZ, 3); context = new Mockery(); mock = context.mock(BookManager.class); client = new BookClient(mock); } public void testDisconnectFail() { String message; context.checking(new Expectations() {{ one (mock).connect(); will(returnValue( true)); one (mock).connect(); will(returnValue( true));
TESTER.PL
Strona 42 z 63
one (mock).bookList(); will(returnValue (bookList)); one (mock).bookList(); will(returnValue (bookList)); one (mock).disconnect(); will(returnVal ue(true)); one (mock).disconnect(); will(returnVal ue(false)); }}); client.getBookList(); message = BookClient.AVAILABLE_BOOKS + BookClient.bookListToString(bookList); assertEquals(message, client.getMessage()); client.getBookList(); message = BookClient.DISCONNECT_ERROR; assertEquals(message, client.getMessage()); context.assertIsSatisfied(); } public void testForException() { String message; final BookOrder bookOrder; bookOrder = new BookOrder(); bookOrder.addBook(CHLOPI); try { context.checking(new Expectations() {{ one (mock).connect(); will(returnVa lue(true)); one (mock).order(bookOrder); will(t hrowException(new BookNotFoundException())); one (mock).disconnect(); will(retur nValue(true)); }}); } catch (BookNotFoundException e) { } catch (NotEnoughBooksException e) { } client.orderBooks(bookOrder); message = BookClient.BOOK_NOT_FOUND_ERROR; assertEquals(message, client.getMessage()); context.assertIsSatisfied(); } }
Główną zaletą uŜycia techniki obiektów zastępczych w porównaniu z innymi technikami
testowania jest moŜliwość weryfikacji zachowań (zarówno prawidłowości wywołań bądź ich
braku, liczby wywołań jak i wartości zwracanych) obiektu testowanego względem środowiska, w
którym pracuje, a nie jedynie weryfikacji zmiany samych stanów testowanego obiektu [4].
Dzięki jej zastosowaniu staramy się lepiej zrozumieć wymagania, które mają być realizowane
przez nasz kod, a tym samym mamy większą wiedzę na temat tego, co powinniśmy zrobić w
najbliŜszym etapie pracy.
TESTER.PL
Strona 43 z 63
Inne drugoplanowe zalety obiektów pozornych, pozwalające lepiej realizować koncepcję
testów jednostkowych to moŜliwość:
• testowania jeszcze mniejszych części kodu niŜ w przypadku pozostałych technik,
• tworzenia testów niezaleŜnych od siebie nawzajem,
• późniejszego podjęcia decyzji o pewnych fragmentach infrastruktury oraz zmniejszenie
ilości kodu testowego, kosztem nieco większej jego złoŜoności.
Zbyt ścisłe zrównoleglenie z kodem testowanym i potrzeba synchronizacji pomiędzy nimi jest
czasem uznawane za jedna z wad, choć w rzeczywistości zapewnia egzekwowanie
przestrzegania ścisłej zgodności z procesem tworzenia testów jednostkowych. Wadą moŜe być
za to bardzo wąski obszar danego scenariusza testowego z uŜyciem mocków, co w przypadku
nawet drobnych zmian w testowanym kodzie moŜe prowadzić do tego, Ŝe test szybciej stanie się
przestarzały i będzie wymagał od nas poprawek [3].
Obiekty zastępcze pozwalają w znacznym stopniu zautomatyzować tworzenie testów
jednostkowych (zwłaszcza, Ŝe istnieje wiele róŜnych narzędzi do ich tworzenia w wielu językach
programowania), a tym samym zwiększyć wydajność oraz przyspieszyć proces tworzenia testów,
powodując, Ŝe powstające oprogramowanie będzie znacznie lepszej jakości. W szczególności
technika ta pozwoli nam na większe zaufanie, co do jakości indywidualnych części naszego
oprogramowania. Pewnymi niedogodnościami mogą być narzędzia do tworzenia obiektów
pozornych (szczególnie dla rzadziej uŜywanych języków programowania), poniewaŜ są stale
rozwijane ze względu to, Ŝe sama idea powstała w miarę niedawno [2]. Oczywiste jest, Ŝe nie
ma jedynego słusznego sposobu na wykonanie testów, a tym samym nie zawsze istnieje
moŜliwość skorzystania z tej wybranej techniki, ale tych wyjątków w przypadku obiektów
zastępczych jest naprawdę niewiele.
Podsumowując obiekty pozorne są i będą waŜną gałęzią testów. Powinny one w
niedługim czasie znacznie się rozpowszechnić, co w połączeniu z technikami zwinnymi
(agile’owymi) będzie potęŜnym narzędziem w tworzeniu oprogramowania.
TESTER.PL
Strona 44 z 63
Bibliografia: [1] 2006. Techniques for Successful Evolutionary/Agile Database Development, artykuł internetowy, http://www.agiledata.org/essays/tdd.html [2] Bain S. 2006. Mocks, Fakes, and Stubs. Net Objectives, Vol. 3, No. 4, pp. 2-14. [3] Brown M., Tapolcsanyi E. 2003. Mock Object Patterns. Proceedings of The 10th Conference on Pattern Languages of Programs, Sept 8-12, USA. [4] Burke E. M., Coyner B. M. 2003. Java Extreme Programming Cookbook. O'Reilly and Associates. [5] Fowler M. 2007. Mocks Aren't Stubs. Artykuł ze strony internetowej autora, http://martinfowler.com/articles/mocksArentStubs.html. [6] Freeman S., Mackinnon T., Pryce N., Walnes J. 2004. Mock Roles Not Objects. Proceedings of 19th Ann. ACM SIGPLAN Conf. Object-Oriented Programming, Systems, Languages, and Applications (OOPSLA '04), ACM Press, pp. 236–246. [7] Freeman S., Pryce N. 2006. Evolving an embedded domain-specific language in Java. Proceedings of the 21th Annual ACM SIGPLAN Conference on Object-Oriented Programming, Systems, Languages, and Applications, OOPSLA 2006, October 22-26, 2006, Portland, Oregon, USA, pp. 855-865. [8] 1999. IEEE Standard for Software Unit Testing: An American National Standard, ANSI/IEEE Std 1008-1987 in IEEE Standards: Software Engineering, Volume Two: Process Standards; The Institute of Electrical and Electronics Engineers, Inc. Software Engineering Technical Committee of the IEEE Computer Society. [9] Mackinnon T., Freeman S., Craig P. 2001. Endo-testing: Unit testing with mock objects. Proceedings of XP2000. Extreme Programming Examined, Addison-Wesley, Boston, MA, pp. 287-301. [10] Massol V., Husted T. 2003. JUnit in Action. Manning Publications. [11] Ryu H.-Y., Sohn B.-K., Park J.-H. 2005. Mock objects framework for TDD in the network environment. Proceedings of the Fourth Annual ACIS International Conference on Computer and Information Science (ICIS’05), pp. 430- 434. [12] Stewart S. 2004. Approaches to Mocking. An article from O'Reilly Network Site, http://www.onjava.com/pub/a/onjava/2004/02/11/mocks.html. [13] Thomas D., Hunt A. 2002. Mock Objects. IEEE Software, Vol. 19, No. 3, pp. 22-24. [14] Wirfs-Brock R.J. 2007. Driven to … Discovering Your Design Values. IEEE Software, Vol. 24, No. 1, pp. 9-11. [15] Keld H. Hansen Using Mock Objects in Java. Artykuł ze strony internetowej, http://javaboutique.internet.com/tutorials/mock_objects/ [16] EasyMock 2.2 Readme, http://www.easymock.org/EasyMock2_2_Documentation.html [17] The jMock Cookbook, http://www.jmock.org/cookbook.html
TESTER.PL
Strona 45 z 63
Dokumentacja – jak to si ę je?
Maciej Dusza
Maciej Dusza jest absolwentem informatyki na wydziale Matematyki,
Informatyki i Mechaniki Uniwersytetu Warszawskiego. W 1993r.
obronił pracę magisterską na temat "Tworzenie programów
współbieŜnych o sterowaniu zadanym strukturami przyczynowo-
skutkowymi". Od tego czasu pracował w kilku firmach w Polsce i USA,
pełniąc funkcje programisty, analityka, projektanta i testera, a przez
ostatnie trzy lata pracował w IMPAQ Sp. z o.o., na stanowisku
Starszego Analityka ds. Zapewnienia Jakości.
Kawaler. Jego hobby to nurkowanie.
TESTER.PL
Strona 46 z 63
Dokumentacja – jak to si ę je?
Maciej Dusza
Pisanie dokumentacji często traktowane jest przez programistów jak cięŜka kara i dopust
boŜy. Z nieco większym zrozumieniem odnoszą się do tego kierownicy projektów, zwłaszcza ci,
którzy kiedyś w połowie projektu stracili pracownika będącego „guru od
systemu/programu/modułu”, i musieli w trybie nagłym wdraŜać do pracy nową osobę,
przegryzając się przez tysiące linii nieudokumentowanego, i często pozbawionego komentarzy
kodu.
Ja osobiście lubię pisać dokumentację. Sprawia mi przyjemność opisywanie
poszczególnych elementów systemu w sposób dokładny, precyzyjny, i zrozumiały dla odbiorcy.
PoniŜej przedstawiam zbiór porad i uwag, które – mam nadzieję – przydadzą się zarówno
osobom piszącym „z potrzeby serca”, jak i tym, dla których jest to przykrym obowiązkiem.
Moje uwagi przedstawiam w postaci krótkich akapitów, odnoszących się do
poszczególnych zagadnień związanych z pisaniem dokumentacji. Opracowałem je na podstawie
własnych doświadczeń, oraz lektury kilku ksiąŜek, których tytuły wymieniam na końcu.
Cechy dobrej dokumentacji:
• jest dokładna i bezbłędna
• jest kompletna
• jest spójna
• jest napisana w sposób klarowny i jednoznaczny
• uŜytkownik moŜe łatwo znaleźć informację, której potrzebuje
• ma porządny, ładny wygląd.
Etapy tworzenia dokumentacji:
• zbieranie informacji na temat opisywanego systemu
• tworzenie projektu dokumentacji
• pisanie dokumentacji
• weryfikacja dokumentacji
• dokonywanie poprawek i uzupełnianie braków.
Dwa ostatnie etapy są zwykle powtarzane kilkakrotnie, aŜ do usunięcia wszystkich usterek. Informacje na temat opisywanego systemu, moŜna zbierać poprzez:
• czytanie juŜ istniejących fragmentów dokumentacji
• pracę z programem i analizę kodu źródłowego
TESTER.PL
Strona 47 z 63
• konsultacje (zazwyczaj z developerami, którzy stworzyli system).
Projekt dokumentacji powinien zawierać następujące elementy:
• tytuł dokumentacji
• rodzaj dokumentacji (np. podręcznik uŜytkownika)
• przewidywana data zakończenia prac nad dokumentacją
• imię i nazwisko dokumentalisty
• krótki opis tego, co dokumentacja będzie zawierać
• szacunkowa liczba stron (najlepiej określić to poprzez porównanie z podobnymi,
istniejącymi juŜ dokumentami)
• spis głównych rozdziałów
• terminy kamieni milowych.
Kamień milowy przy pisaniu dokumentacji, to moment kiedy dokumentacja idzie do weryfikacji.
Dobrym miejscem na ustanowienie pierwszego kamienia milowego, jest moment gdy:
• większość (dwie trzecie lub trzy czwarte) tekstu jest juŜ napisane
• zaznaczone są miejsca, w których wstawione zostaną rysunki i zrzuty ekranów.
Dobrym miejscem na ustanowienie drugiego kamienia milowego, jest moment gdy:
• praktycznie cały tekst jest juŜ napisany
• prawie wszystkie rysunki i zrzuty ekranów są juŜ w dokumentacji
• poprawione zostały usterki, które wyszły na jaw w czasie weryfikacji po pierwszym
kamieniu milowym.
Przy tworzeniu dokumentacji, zwykle występują co najmniej dwa kamienie milowe, i często nie
ma ich więcej. Dlatego w projekcie dokumentacji podaje się najczęściej terminy dwóch kamieni.
Weryfikacja dokumentacji oznacza:
• dokładne przeczytanie dokumentacji w poszukiwaniu błędów
• sprawdzenie czy zrzuty ekranu odpowiadają temu, co rzeczywiście w opisywanym
momencie widać na ekranie
• wykonanie procedur (instrukcji) zawartych w dokumentacji, i sprawdzenie czy
rzeczywiście generują Ŝądane rezultaty
• przekazanie dokumentacji recenzentom i zebranie ich uwag.
PoŜyteczną metodą weryfikacji, jest równieŜ poproszenie kogoś, kto nie posiada zbyt
głębokiej wiedzy na temat opisywanego systemu, o przeczytanie dokumentacji, i upewnienie
się, Ŝe wszystko zrozumiał. Powód: dokumentalista moŜe zapomnieć o napisaniu czegoś, co jest
dla niego "oczywiste", a recenzent, zwykle dobrze znający system, moŜe nie zauwaŜyć takiego
braku.
TESTER.PL
Strona 48 z 63
Dwa waŜne pytania, jakie naleŜy sobie zadać przed rozpoczęciem pracy nad dokumentacją:
• dla kogo ta dokumentacja jest przeznaczona? Inaczej pisze się np. dla sprzedawcy, który
będzie jedynie korzystał z systemu, a inaczej dla programisty, który będzie ten system
rozwijał. Nie chodzi tu tylko o treść, chodzi równieŜ o styl pisania (np. uŜywanie
słownictwa technicznego).
• jakie przyjąć podejście: opisowe czy zadaniowe? Opisowe podejście do pisania
dokumentacji polega na tym, Ŝe po prostu opisujemy kolejne elementy systemu,
troszcząc się jedynie o to, Ŝeby zrobić to dobrze. Podejście zadaniowe polega na tym, Ŝe
przy pisaniu bierzemy pod uwagę zadania, które wykonuje odbiorca dokumentacji.
Przykładowo: załóŜmy, Ŝe opisujemy interfejs uŜytkownika, a odbiorcą dokumentacji ma być
osoba zajmująca się wystawianiem faktur. Jeśli przyjmiemy podejście zadaniowe, to opcje
systemu opiszemy nie w takiej kolejności, w jakiej są ułoŜone w menu, tylko w takiej, w jakiej
korzysta się z nich przy wystawianiu faktur.
MoŜe się zdarzyć, Ŝe z dokumentacji mają korzystać dwie róŜne grupy uŜytkowników. Na
przykład sprzedajemy system wspomagający sprzedaŜ firmie, która posiada dział sprzedaŜy i
dział informatyki. Sprzedawcy będą uŜywać tego systemu korzystając z interfejsu uŜytkownika,
a informatycy otrzymają kod źródłowy, i będą go na własną rękę rozwijać. W takiej sytuacji,
najlepszym rozwiązaniem jest napisanie dwóch oddzielnych dokumentacji: jednej dla
sprzedawców, i jednej dla informatyków. Jest to oczywiście bardziej praco- i czasochłonne, ale
znacznie wygodniejsze z punktu widzenia odbiorców dokumentacji. Jeśli jednak nie chcemy
pisać dwóch oddzielnych dokumentacji (bo np. nie ma na to czasu), i decydujemy się włoŜyć
wszystkie informacje do jednej dokumentacji, wówczas naleŜy wyraźnie zaznaczyć, które sekcje
dokumentacji są przeznaczone dla której grupy odbiorców.
Pisanie dokumentacji jednym ciągiem, od początku do końca, nie jest dobrym pomysłem. Po
pierwsze, nieraz będą się zdarzać sytuacje, kiedy napisanie kolejnego fragmentu nie jest
moŜliwe (bo np. developer, z którym trzeba się skonsultować, nie jest chwilowo dostępny). Po
drugie, po zakończeniu moŜe się okazać, Ŝe dokumentacja wprawdzie zawiera wszystko co
trzeba, ale jej układ powinien być inny. Dlatego lepsze wyniki przynosi następujące podejście:
• określamy jakie rozdziały będzie mieć dokumentacja
• dla kaŜdego rozdziału określamy jakie będzie mieć podrozdziały
• dla kaŜdego podrozdziału określamy jakie będzie mieć pod-podrozdziały
• i tak dalej...
• kiedy szczegółowa struktura rozdziałów jest juŜ gotowa, zaczynamy wypełniać treścią
kolejne pod-...-rozdziały. Jeśli w jakimś momencie napotkamy problem, z którym nie
TESTER.PL
Strona 49 z 63
moŜemy sobie od razu poradzić, wtedy zaznaczamy Ŝe to miejsce wymaga uzupełnienia,
i po prostu zabieramy się za wypełnianie treścią kolejnego elementu struktury.
Dodatkową zaletą takiego podejścia jest to, Ŝe na pierwszy rzut oka widoczny jest stan prac
nad dokumentacją - co konkretnie jest juŜ gotowe, co wymaga uzupełnienia, a co nie jest
jeszcze rozpoczęte.
Na początku dokumentacji powinny się znaleźć:
• copyright (najlepiej zwrócić się do działu prawnego firmy o opracowanie dokładnego
sformułowania)
• spis treści
• opcjonalnie: spis ilustracji (dla uŜytkownika moŜe być wygodne, jeśli będzie mógł znaleźć
konkretny diagram, bez zastanawiania się w jakim powinien być rozdziale)
• wstęp.
Wstęp powinien informować:
• jaki produkt opisuje dokumentacja
• dla kogo dokumentacja jest przeznaczona
• co dokumentacja zawiera (bardzo ogólnie)
• jakie konwencje są stosowane w dokumentacji (np. jaka czcionka jest stosowana dla
zamieszczonych w dokumentacji fragmentów kodu źródłowego).
Na końcu dokumentacji powinny się znaleźć:
• załączniki
• słowniczek terminów specyficznych dla opisywanego systemu, oraz terminów i skrótów
które są uŜywane w dokumentacji, a których uŜytkownik moŜe nie znać
• indeks.
Załączniki powinny zawierać informacje, które uŜytkownik moŜe chcieć uzyskać, ale które nie
są niezbędne do zrozumienia dokumentacji (np. definicje pól w bazie danych). Uwaga: nie
naleŜy traktować załączników jako miejsce, do którego dokumentalista moŜe wrzucić wszystkie
informacje, co do których nie ma pewności gdzie je umieścić.
Indeks jest bardzo waŜnym elementem dokumentacji. To w duŜym stopniu od niego zaleŜy,
na ile dokumentacja będzie uŜyteczna dla uŜytkownika.
Kiedy prace nad dokumentacją dojdą do kamienia milowego, przy którym wskazane jest
przeprowadzenie weryfikacji tego, co zostało dotychczas stworzone, dokumentalista powinien
najpierw sam sprawdzić swoją pracę, a następnie poprosić kilka osób o recenzję. Naturalnymi
kandydatami na recenzentów są developerzy pracujący nad opisywanym systemem, i szef
TESTER.PL
Strona 50 z 63
dokumentalisty. Warto zwrócić się o to równieŜ do ludzi, którzy mają codzienny kontakt z
klientem - odbiorcą dokumentacji (czyli do pracowników działu sprzedaŜy, działu marketingu, i
działu pomocy technicznej).
UwaŜne przeczytanie dokumentacji wymaga czasu. Dlatego recenzentów naleŜy
z wyprzedzeniem zawiadomić o tym, Ŝe danego dnia przyśle im się dokumentację do
zrecenzowania.
Istnieją trzy metody zbierania opinii od recenzentów.
Pierwsza, najbardziej efektywna, polega na tym, Ŝe dokumentalista i wszyscy
recenzenci spotykają się razem, siadają przy stole, przechodzą po kolei przez wszystkie rozdziały
i akapity dokumentacji, kaŜdy moŜe zgłaszać na głos swoje uwagi, a pozostali od razu
ustosunkowują się do tych uwag. Dzięki temu, kaŜda sugestia, jaką ktoś moŜe mieć, jest
rozpatrywana przez cały zespół recenzentów.
Uwaga: na takim spotkaniu nieraz zdarza się, Ŝe rozmowa zaczyna odbiegać od tematu
(np. developer zaczyna mówić o pracach nad modułem, który nie wchodzi w zakres systemu
objęty dokumentacją). Im więcej ludzi bierze udział w spotkaniu, tym częściej zdarzają się takie
mimowolne odejścia od tematu. Dlatego, jeśli recenzentów jest więcej niŜ kilku, warto poprosić
kogoś, kto sam nie bierze udziału w recenzowaniu, o pełnienie funkcji moderatora. Moderator
jest obecny na zebraniu, ale nie zabiera głosu w dyskusji. Jedyne, czym się zajmuje, to
słuchanie tego, co mówią inni, i przerywanie ludziom, którzy zaczynają odchodzić od tematu.
Druga metoda zbierania opinii, polega na rozesłaniu dokumentacji do wszystkich
recenzentów, odebraniu opinii od kaŜdego oddzielnie, i skonsolidowaniu otrzymanych uwag.
Szczególną uwagę dokumentalista musi tu zwrócić na sprzeczne sugestie, które mogą nadejść
od róŜnych recenzentów. W takim przypadku naleŜy zawiadomić autorów tych sugestii o
zaistniałej sytuacji, i poprosić o przemyślenie stanowiska drugiej osoby. Jeśli Ŝaden z
recenzentów nie chce ustąpić, a dokumentalista nie ma własnego zdania w tej kwestii, właściwe
wydaje się uwzględnienie propozycji recenzenta, zajmującego wyŜsze stanowisko w hierarchii
firmy. Jeśli jednak dokumentalista skłania się ku rozwiązaniu proponowanemu przez niŜej
stojącego recenzenta, powinien skonsultować się ze swoim szefem.
Trzecia metoda zbierania opinii, polega na wysłaniu dokumentacji do jednego
z recenzentów, następnie, razem z naniesionymi przez niego uwagami, do drugiego, potem z
uwagami naniesionymi przez tych dwóch do trzeciego, i tak dalej. Dzięki temu kaŜdy (prócz
pierwszego) recenzent, moŜe odnieść się nie tylko do samej dokumentacji, ale równieŜ do uwag
poprzednich recenzentów. Metoda ta zabiera oczywiście więcej czasu, niŜ dwie pozostałe
metody.
TESTER.PL
Strona 51 z 63
Jeśli przekazuje się do recenzji dokument, który był juŜ kiedyś recenzowany, naleŜy
zaznaczyć co zostało dodane lub zmienione od czasu poprzedniej recenzji, Ŝeby recenzenci nie
musieli ponownie czytać wszystkiego od A do Z.
Kiedy dokumentacja zostaje oddana do produkcji, następuje jej "zamroŜenie". Oznacza
to, Ŝe Ŝadne zmiany nie będą juŜ wprowadzane. Jeśli przed przekazaniem dokumentacji
odbiorcy, okaŜe się Ŝe coś wymaga zmiany, do dokumentacji zostanie dołączona errata (np. plik
README na CD z dokumentacją), a potrzebne zmiany zostaną wprowadzone dopiero
w następnej wersji dokumentacji.
WaŜną rzeczą jest bardzo dokładne zebranie uwag od odbiorców dokumentacji, po
dostarczeniu im pierwszej gotowej części. Na podstawie takich uwag moŜna nie tylko stworzyć
wskazówki przydatne w dalszych pracach nad dokumentacją, ale moŜe to równieŜ prowadzić do
zmiany przyjętych standardów (najprostszy przykład: odbiorca prosi o pisanie dokumentacji przy
uŜyciu większej czcionki, bo ma słaby wzrok). Opinie odbiorców naleŜy zbierać po przekazaniu
im kaŜdej części dokumentacji, jednak szczególnie waŜne jest to na początku, z powodów
wymienionych wyŜej.
Przed rozpoczęciem pisania dokumentacji, naleŜy ustalić symbol / ciąg znaków, który
będzie stosowany w miejscach wymagających uzupełnienia. Takim symbolem moŜe być np. ciąg
liter TBD (od ang. to be determined). Jeśli osoba pisząca dokumentację, nie będzie pewna co
napisać w jakimś miejscu (bo np. wymaga to konsultacji z developerem), to moŜe kontynuować
pisanie pod warunkiem wstawienia w to miejsce takiego symbolu. Obowiązuje zakaz oznaczania
miejsc wymagających uzupełnienia w jakikolwiek inny sposób (np. pisząc: do uzupełnienia).
Powód jest oczywisty: chodzi o to, Ŝeby w kaŜdej chwili moŜna było jednym find'em znaleźć
wszystkie niedokończone miejsca.
Jeśli wskazane jest umieszczenie w dokumentacji zrzutu jakiegoś ekranu, to ekran ten
powinien zawierać konkretne dane, a nie tylko puste pola. Przykładowo, jeśli na ekranie jest
okno słuŜące do wprowadzania informacji personalnych, to naleŜy do odpowiednich pól
wprowadzić zmyślone imię, nazwisko, adres, telefon itd. Uwaga: niedopuszczalne jest
wprowadzanie danych Ŝyjących osób (np. przepisywanie z ksiąŜki telefonicznej), moŜe to grozić
procesem sądowym.
Kiedy pisze się dokumentację, precyzja i klarowność sformułowań są waŜniejsze od
elegancji. Jeśli np. w jednym zdaniu pojawi się dziesięć razy słowo system, to nie ma w tym nic
niewłaściwego. Nie naleŜy pisać na zmianę system i np. program, bo moŜe to jedynie wprawić w
zakłopotanie odbiorcę dokumentacji, który zacznie się zastanawiać czy na pewno chodzi o to
samo. Na tej samej zasadzie, naleŜy trzymać się raz przyjętych terminów na określenie pewnych
TESTER.PL
Strona 52 z 63
rzeczy czy czynności. Jeśli np. w pierwszym rozdziale piszemy o klikaniu myszą, to juŜ do końca
powinniśmy konsekwentnie uŜywać tego określenia, a nie zastępować go w innym rozdziale
słowem tupanie myszą.
Czasem moŜe się zdarzyć, Ŝe trzeba wybierać między ścisłym trzymaniem się zasad
pisowni, a klarownością przekazu. W takim przypadku lepiej złamać zasady, Ŝeby w zamian za
to uzyskać jednoznaczny i zrozumiały przekaz. Przykładowo, weźmy następujące zdanie:
„systemy: A, B, C i D”. Czytelnik moŜe mieć wątpliwości, czy chodzi tu o cztery systemy, czy teŜ
o trzy, z których ostatni ma złoŜoną nazwę „C i D”. Jeśli dodamy przecinek po „C”, usuniemy
niejednoznaczność.
NaleŜy pamiętać, Ŝe dokumentacja jest przeznaczona dla człowieka, a nie dla komputera,
i dlatego mogą się zdarzać sytuacje, w których uzasadnione jest odstąpienie od przyjętych
standardów. Przykładowo, jeśli chcemy umieścić w dokumentacji diagram przejścia stanów, ale
widzimy Ŝe taki diagram byłby bardzo skomplikowany, czytelnik niewiele by z niego rozumiał, i
tylko co chwila by błądził nawigując po plątaninie strzałek, to lepiej w ogóle zrezygnować z
diagramu, a poszczególne stany i warunki przejścia między nimi, opisać słownie.
Jeśli dokumentalista przejmuje dokumentację napisaną przez kogoś innego, to zanim zacznie
dopisywać nowe rozdziały, powinien:
• przeczytać to, co juŜ jest napisane
• jeśli jest to moŜliwe, porozmawiać z poprzednim autorem dokumentacji, i dowiedzieć się
czego nie zdąŜył napisać, co zamierzał zmienić, itp.
• usiąść nad dokumentacją razem z developerami, upewnić się Ŝe w dokumentacji nie ma
błędów, oraz dowiedzieć się co nowego pojawiło się w systemie
• samemu obejrzeć opisywany system, i stwierdzić na ile pasuje do dokumentacji
• dowiedzieć się, czy odbiorcy dokumentacji zgłaszali jakieś uwagi lub prosili o zmiany w
dokumentacji.
Kiedy dokumentalista po raz pierwszy uruchamia system, który ma opisywać, i próbuje
działać jako uŜytkownik, powinien zapisywać wszystkie rzeczy, które sprawiły mu trudność. Jest
bardzo prawdopodobne, Ŝe rzeczywisty uŜytkownik natknie się na takie same trudności, a co za
tym idzie jest to okazja do zlokalizowania miejsc, które warto opisać w dokumentacji szczególnie
dokładnie.
Kiedy dokumentalista rozpoczyna opisywanie systemu, i otrzymuje dostęp do kodu
źródłowego, powinien upewnić się, Ŝe jest to najnowsza wersja kodu rozwojowego, nad którym
prowadzone są prace. Nie moŜe to być stara wersja kodu, a w szczególności nie moŜe to być
kod okrojonej wersji demonstracyjnej. Musi to być aktualny kod, nawet jeśli codziennie miałby
się zmieniać.
TESTER.PL
Strona 53 z 63
Jeśli system, dla którego pisze się dokumentację, podlega rozwojowi w trakcie pisania
dokumentacji, naleŜy zobowiązać developerów do informowania dokumentalisty o zmianach
dokonywanych w kodzie. Nie muszą to być szczegółowe raporty, wystarczy raz dziennie wysłać
mail z informacją: zmieniłem klasę taką i taką. Dokumentalista sam zdecyduje, czy taka zmiana
wymaga modyfikowania dokumentacji, a jeśli tak to poprosi developera o dokładniejsze
informacje.
Jeśli w trakcie prac nad dokumentacją, pojawi się konieczność konsultacji z developerem,
naleŜy na początek zwrócić się do osoby stojącej moŜliwie nisko w hierarchii. Czyli np. najpierw
naleŜy porozmawiać z programistą, jeśli nie potrafi udzielić odpowiedzi to z szefem zespołu
programistów, a jeśli on teŜ nie potrafi, to dopiero wtedy naleŜy poprosić o konsultację
kierownika całego projektu. Powód: im wyŜej w hierarchii stoi dana osoba, tym bardziej jej czas
jest cenny dla firmy.
Przed pójściem na konsultacje, naleŜy się przygotować, to znaczy samemu dowiedzieć się
tyle na interesujący temat, ile się da. Dzięki temu będzie moŜna zadawać potem precyzyjne
pytania, i lepiej rozumieć odpowiedzi. Zawsze warto przyjść na spotkanie z przygotowaną listą
konkretnych pytań. Taką listę warto równieŜ wysłać rozmówcy mailem, przed spotkaniem, Ŝeby
mógł się przygotować (nie musi mieć w głowie gotowej odpowiedzi na kaŜde pytanie).
Jeśli trzeba przeprowadzić konsultacje z osobą, która ma mało czasu, to zamiast robić
notatki w trakcie rozmowy, lepiej uŜyć dyktafonu. Uwaga: w takiej sytuacji naleŜy od razu na
początku rozmowy połoŜyć dyktafon na stole, i wyjaśnić, Ŝe dzięki temu zaoszczędzi się czas.
Nie wypada natomiast trzymać dyktafonu w kieszeni, i dopiero w połowie rozmowy, na pytanie
czy nie warto byłoby robić notatki, odpowiedzieć Ŝe rozmowa nagrywa się na ukryty
magnetofon.
Dla niektórych ludzi moŜe być denerwujące, Ŝe w czasie konsultacji muszą co chwila robić
"bezproduktywne" przerwy, Ŝeby dokumentalista mógł robić notatki. Jednym sposobem na to
jest uŜywanie dyktafonu, a innym - spotkanie się w czasie, gdy konsultant (nie dokumentalista!)
będzie jadł obiad. Kiedy dokumentalista będzie spokojnie robił notatki, konsultant będzie jadł, i
nie będzie miał poczucia, Ŝe marnuje czas.
MoŜe się zdarzyć, Ŝe osoba, z którą dokumentalista chce się skonsultować, nigdy nie ma na
to czasu. W takiej sytuacji naleŜy poprosić, Ŝeby sama wyznaczyła dogodny dla niej termin.
Czasem taką prośbę trzeba powtórzyć wiele razy, Ŝeby odniosła skutek. Jeśli jednak nic to nie
daje, naleŜy zastanowić się czy jest ktoś inny, od kogo moŜna uzyskać dane informacje. Jeśli to
równieŜ jest niemoŜliwe, naleŜy przedstawić problem swojemu szefowi, i poprosić go o
interwencję.
TESTER.PL
Strona 54 z 63
Na koniec konsultacji, po wyjaśnieniu wszystkich wątpliwości, warto zadać pytanie: czy jest
coś jeszcze, o czym powinienem wiedzieć? W ten sposób moŜna czasem uzyskać informacje o
czymś, co samo nie przyszłoby do głowy.
Jeśli kończy się czas zaplanowany na konsultacje, a nie wszystko jeszcze zostało omówione,
to nie naleŜy przeciągać spotkania, tylko zaproponować ustalenie następnego terminu.
Po zakończeniu konsultacji, najlepiej jest od razu dodać uzyskane informacje do pisanej
dokumentacji. W przeciwnym razie, moŜna mieć później problemy z rozszyfrowaniem robionych
skrótami notatek z rozmowy.
Po przekazaniu dokumentacji do odbiorcy, warto zwrócić uwagę na to, z jakimi problemami
ten odbiorca zwraca się do działu obsługi klienta. Jeśli ma problemy z czymś, co zostało opisane
w dokumentacji, moŜe to znaczyć Ŝe dany fragment dokumentacji zawiera błędy, lub został
napisany w sposób niezrozumiały albo niedostatecznie szczegółowy.
W obrębie całej dokumentacji, naleŜy uŜywać jednolitego zestawu stylów pisma. Jest to
szczególnie waŜne wtedy, gdy nad dokumentacją pracuje więcej niŜ jedna osoba. Dzięki
jednolitemu zestawowi stylów, rozdziały pisane przez róŜne osoby nie będą się róŜnić wyglądem.
Typowe elementy dokumentacji, dla których trzeba zdefiniować (i konsekwentnie stosować)
style, to:
• nagłówek rozdziału głównego
• nagłówek podrozdziału
• nagłówek pod-podrozdziału
• i tak dalej...
• "zwykły" tekst
• lista numerowana
• lista wypunktowana
• tekst przesunięty w prawo, stanowiący kontynuację (od nowego wiersza) tekstu z listy
numerowanej lub wypunktowanej
• fragment kodu źródłowego
• podpis pod rysunkiem.
Kluczowe informacje powinny być wyeksponowane, tak Ŝeby były widoczne od razu po
otworzeniu dokumentacji na danej stronie. Jeśli np. najwaŜniejszym elementem jakiegoś
rozdziału jest opis czynności, które naleŜy wykonać, to lepiej umieścić w rozdziale numerowaną
listę z tymi czynnościami, niŜ wymienić je po przecinku w jednym zdaniu, ukrytym wśród innych
zdań. Taki sposób jest nie tylko bardziej elegancki, ale i bardziej praktyczny. Kiedy uŜytkownik
TESTER.PL
Strona 55 z 63
będzie wykonywał te czynności, odrywając co chwilę wzrok od dokumentacji, dzięki liście będzie
mógł szybciej znaleźć właściwe miejsce, gdy ponownie spojrzy na kartkę.
DuŜa liczba małych rozdziałów jest lepsza niŜ niewielka liczba obszernych rozdziałów. Przy
małych rozdziałach uŜytkownik moŜe łatwiej znaleźć konkretną informację.
Zasada KISS: Keep It Short and Simple. Czytelnik łatwiej rozumie kilka krótkich, prostych
zdań, niŜ jedno długie zdanie złoŜone. Analogicznie, czytelnik łatwiej rozumie kilka krótkich
akapitów, niŜ jeden długi.
Jeśli w dokumentacji występują słowa lub skróty, których uŜytkownik moŜe nie znać, naleŜy
wyjaśnić ich znaczenie. MoŜna to zrobić na dwa sposoby: umieszczając na końcu dokumentacji
słowniczek ze wszystkimi takimi pojęciami, lub wyjaśniając znaczenie kaŜdego pojęcia przy jego
pierwszym wystąpieniu w dokumentacji. Pierwszy sposób (słowniczek) jest zdecydowanie
lepszy. Dokumentacja to nie powieść, i nie moŜna zakładać, Ŝe uŜytkownik będzie czytał
wszystkie rozdziały po kolei.
śeby uniknąć błędów ortograficznych w dokumentacji, nie wystarczy włączyć w edytorze
opcję sprawdzania pisowni. Zdarzają się błędy, których automatyczna kontrola nie wykryje (np.
jeśli błąd literowy spowoduje zamianę jakiegoś słowa na inne poprawne słowo).
Przy wyszukiwaniu błędów, które mogły powstać w czasie wprowadzania tekstu, najlepiej
jest wydrukować dokumentację i sprawdzić wydruk. Powód: oko ludzkie łatwiej wychwytuje
błędy na papierze niŜ na ekranie.
W czasie takiego sprawdzania, szczególną uwagę naleŜy zwrócić na:
• ortografię, gramatykę i interpunkcję
• imiona, nazwiska, inicjały i tytuły
• nazwy firm
• inne nazwy własne
• liczby
• daty.
Wyszukiwania błędów, które mogły powstać w czasie wprowadzania tekstu, nie naleŜy
łączyć z wyszukiwaniem błędów merytorycznych. Za wyszukiwanie błędów literowych, najlepiej
zabrać się dopiero po zakończeniu sprawdzania (i poprawiania) błędów merytorycznych. Powód:
błędy literowe najłatwiej zauwaŜyć, kiedy człowiek nie zastanawia się nad sensem danego
zdania czy akapitu. Jedną z metod jest sprawdzanie kolejnych akapitów poczynając od końca
rozdziału. Pozwala to skoncentrować się na pisowni, bez zwracania uwagi na treść.
TESTER.PL
Strona 56 z 63
Zanim dokumentalista przekaŜe dokumentację recenzentom, powinien upewnić się, Ŝe jego
własnym zdaniem wszystko w niej jest w porządku. W tym celu, oprócz sprawdzenia Ŝe
dokumentacja nie zawiera błędów, powinien zadać sobie następujące pytania:
• czy dokumentacja jest wystarczająco obszerna, jak na obecny kamień milowy?
• czy informacje są właściwie zorganizowane (ułoŜone)?
• czy informacje techniczne są dokładne?
• czy pojęcia, których uŜytkownik moŜe nie znać, są wyjaśnione?
• czy język dokumentacji jest spójny?
• czy przykłady są dobrze dobrane i umieszczone w odpowiednich miejscach?
• czy numery stron w spisie treści i w indeksie są poprawne?
Po zakończeniu pracy nad dokumentacją, bardzo poŜyteczne jest zrobienie podsumowania
całego przebiegu pracy. Chodzi o to, Ŝeby ustalić co poszło dobrze, z czym były problemy, i jak
moŜna by takich problemów uniknąć w przyszłości. Jeśli nad dokumentacją pracowało kilka
osób, to najlepiej urządzić spotkanie. Podstawowe pytania, które naleŜy zadać w trakcie takiego
spotkania, to:
• ile czasu zajęło napisanie tej dokumentacji, a ile powinno zająć?
• jakie problemy przeszkadzały w pracy lub spowalniały ją?
• co (np. jakie narzędzie) było poŜyteczne i pomocne?
• które osoby były uczynne i chętne do pomocy?
• ile czasu pochłonęło samo czekanie na informacje?
• czy komunikacja między osobami piszącymi dokumentację była dobra?
• czy komunikacja z osobami udzielającymi konsultacji była dobra?
• co moŜna zrobić, Ŝeby następną dokumentację napisać lepiej lub szybciej?
Na koniec, chciałbym polecić trzy ksiąŜki, z których korzystałem przy pisaniu tego artykułu:
• The Complete Idiot's Guide to Technical Writing, Krista Van Laan & Catherine Julian,
“Alpha Books”, 2001.
Tą ksiąŜkę polecam najbardziej, jeśli ktoś nie wstydzi się takiego tytułu na półce.
• Technical Writing for Dummies, Sheryl Lindsell-Roberts, “Hungry Minds, Inc.”, 2001
• The User Manual Manual : How to Research, Write, Test, Edit & Produce a Software
Manual, Michael Bremer, “UnTechnical Press”, 1999
TESTER.PL
Strona 57 z 63
SQS Software & Systems Quality Conferences
Düsseldorf 2007
Relacja z konferencji
Łukasz śebrowski
Software Quality Engineer w firmie GTECH EE, od prawie czterech lat zawodowo zajmuje się jakością oprogramowania specjalizując się m.in. w automatyzacji testów. Przewodniczący Komisji Akredytacyjnej SJSI.
TESTER.PL
Strona 58 z 63
SQS Software & Systems Quality Conferences
Düsseldorf 2007
Relacja z konferencji
Łukasz śebrowski
W dniach 25-27 kwietnia 2007 roku Düsseldorf po raz kolejny gościł osoby zajmujące się
jakością oprogramowania. Do Centrum Kongresowego Düsseldorf przybyło 810 uczestników
oraz ponad 40 wystawców. Podobnie jak to miało miejsce podczas ubiegłorocznej edycji
konferencji ICSTEST, zdecydowana większość uczestników pochodziła z Niemiec, lecz wśród
uczestników moŜna było spotkać równieŜ osoby m.in. z Finlandii, Francji, Hiszpanii, Holandii,
Indii, Korei Płd., USA i Wlk. Brytanii. Dwie prezentacje zostały poprowadzone przez naszych
rodaków, natomiast ja reprezentowałem Stowarzyszenie Jakości Systemów Informatycznych,
które jest członkiem wspierającym tej konferencji.
Rysunek 1. WybrzeŜe Renu w Düsseldorfie (fot. autora)
TESTER.PL
Strona 59 z 63
Ilość przybyłych gości, róŜnorodność branŜ, które reprezentowali oraz zagadnienia tam
prezentowane świadczą, Ŝe zagadnienie jakości oprogramowania jest waŜnym i coraz bardziej
docenianym działem inŜynierii oprogramowania.
Konferencja podzielona została na dwa obszary funkcjonalne: Zarządzanie Jakością oraz
Testowanie. W ramach kaŜdego z tych obszarów prowadzone były trzy równoległe bloki
tematyczne (a w przypadku Testowania drugiego i trzeciego dnia cztery równoległe bloki).
Zdecydowana większość prezentacji dotyczących Zarządzania Jakością wygłoszona była w jęz.
niemieckim i dotyczyła takich zagadnień jak: modele procesów zapewnienia jakości,
optymalizacja procesów, zarządzanie produktem, zarządzanie wymaganiami, CMMI, outsourcing,
SPICE oraz miary testowania. Testowanie natomiast zdominowane było przez prezentacje w jęz.
angielskim dotyczące zarządzania testami, strategii testowania, offshore testing, TTCN-3,
systemów wbudowanych, walidacji oprogramowania w branŜy medycznej, agile testing,
bezpiecznych e-transakcji, automatyzacji testów oraz metryk. Całości dopełniały tutoriale
(płatne), które odbyły się dzień przed konferencją, warsztaty, które odbywały się równolegle z
prezentacjami, a takŜe prezentacje wystawców.
Nie zabrakło równieŜ wykładów plenarnych na początek i na koniec kaŜdego dnia. Wobec
duŜej ilości wraŜeń podczas tych trzech dni konferencji w pamięci najbardziej utkwiły mi wykład
pierwszy oraz ostatni. Konferencję rozpoczęła pani Theresa Lanowitz(USA) z firmy voke inc.
wykładem „Transformacja Jakości w Przedsiębiorstwie”, w którym przedstawiła wizję działań w
dziedzinie jakości oprogramowania, które przedsiębiorstwa powinny podejmować, aby móc
dostosowywać się do zmieniającej się rzeczywistości. Jednym z ciekawych stwierdzeń, które tam
padło była prognoza, Ŝe w roku 2014 nastąpi globalny niedobór wykwalifikowanych
pracowników w branŜy IT, w następstwie coraz większego przenikania informatyki do naszego
codziennego Ŝycia. No cóŜ, poŜyjemy zobaczymy.
TESTER.PL
Strona 60 z 63
Rysunek 2. Wykład Theresy Lanovitz (fot. autora)
Konferencję zakończył Prof. Sachar Paulus(D) Chief Security Officer w firmie SAP
wykładem „Mierzenie bezpieczeństwa – potrzeby i wyzwania z róŜnych punktów widzenia”.
Najpierw zdefiniował on bezpieczeństwo jako nie robienie niczego, co nie jest oczekiwane, w
nawiązaniu do definicji jakości, która jest robieniem tego, co jest oczekiwane. Następnie
dzisiejsze trendy w produkcji oprogramowania określił jako odejście od budowy słonia i
zarządzania nim, na rzecz utrzymywania i kierowania koloniami mrówek (Prof. stwierdził
„Zaufanie nabiera nowego znaczenia”;-). Na końcu zaprezentował najpowaŜniejsze wyzwanie w
dziedzinie bezpieczeństwa: jak zarządzać bezpieczeństwem nie potrafiąc go mierzyć i szacować
prawdopodobieństwa wystąpienia zagroŜenia, nie mając standardów i miar. O pomoc w
wypracowaniu tych narzędzi zwrócił się do środowiska osób związanych z jakością, którzy, na co
dzień stają przecieŜ przed podobnymi problemami. Wykład ten dał mi duŜo do myślenia, a
wychodząc z Congress Center Düsseldorf po raz ostatni, nie czułem, Ŝe to juŜ koniec, lecz Ŝe
przygoda dopiero się zaczyna.
Poziom merytoryczny prezentacji podczas konferencji był zróŜnicowany. Generalnie
zasada podąŜania za tłumem sprawdzała się. Ciekawe prezentacje gromadziły duŜo więcej osób
niŜ te nudne, (choć moŜe to brak audytorium demotywował prelegentów). NiezaleŜnie od
poziomu wystąpienia, kaŜdy prelegent w podziękowaniu otrzymywał dwie butelki wina. Fakt, Ŝe
równocześnie odbywało się kilka prezentacji zmuszał do dokładnego przestudiowania programu
konferencji na dany dzień, aby wybrać dla siebie to co zapowiadało się najciekawiej. W ramach
bloku zarządzania testami interesującą prezentację przedstawili Michael Bangel z DB Systems
oraz Dr. Stephan Fassbender z C1 SetCon. Było to swego rodzaju Case Study przedstawiające
przebieg wdroŜenia narzędzia do zarządzania testami (jednego z tych najdroŜszych
komercyjnych) w spółce prowadzącej obsługę informatyczną Kolei Niemieckich. Pokazali m.in.
TESTER.PL
Strona 61 z 63
strukturę organizacyjną prowadzonych projektów w firmie(jedno narzędzie miało obsługiwać
wszystkie projekty), wyszczególnione fazy wdroŜenia – całość trwała 18 miesięcy, kryteria
doboru projektu pilotaŜowego, model księgowania kosztów narzędzia, sposoby przekonywania
zarządu oraz uŜytkowników do narzędzia, podsumowanie kluczowych czynników dla pomyślnego
wdroŜenia. Polecam prezentację wszystkim, którzy uwaŜają, Ŝe wystarczy kupić licencję na
narzędzie i przykazać testerowi, aby od tej chwili uŜywał właśnie tego.
Rysunek 3. LTUarena (fot. autora)
Kolejne ciekawe wystąpienie, o którym warto wspomnieć zaprezentowali Adam Wolszczak
i Marcin Dąbrowski z polskiego oddziału HP. W procesie testowania systemów Data Warehouse
wyodrębnili oni 15 obszarów (m.in. testy migracji danych, testy wydajnościowe, funkcjonalne,
uŜyteczności, itd.) a następnie kaŜdy z nich przeanalizowali za pomocą czterech kryteriów
(zdolność do ponownego wykorzystania, łatwość wykonania, dostępność narzędzi, zwrot z
inwestycji) pod kątem podatności na automatyzację. W podsumowaniu wymienili kilka
praktycznych wskazówek dotyczących automatyzacji testów oraz wskazali źródła, z których
moŜna czerpać wiedzę o automatyzacji. Ta konkretna i uporządkowana prezentacja zagadnienia
opatrzona wyczerpującym wyjaśnieniem, dlaczego dany obszar otrzymał taką a nie inną ocenę,
spotkała się z dobrym przyjęciem przez słuchaczy. Miłe słowo na temat narzędzi open source z
ust pracowników HP (od niedawna Mercury naleŜy do HP) dla niektórych było zaskoczeniem.
Ostatnią prezentację w bloku automatyzacji testów wygłosił B. Rollinson, Test Architect
z firmy Microsoft. Wychodząc naprzeciw oczekiwaniom słuchaczy zaprezentował darmowe
TESTER.PL
Strona 62 z 63
narzędzie Visual Studio C# Express Edition. Na kilku prostych przykładach z rodzaju Getting
Started zaprezentował zalety języka C# do automatyzacji testów aplikacji windowsowych.
Niewątpliwa wiedza merytoryczna, łatwość nawiązywania kontaktu z publicznością uzupełniona
opowiastkami jak to się robi w Microsofcie pozwoliły mi zapamiętać tą prezentację jako dobrze
spędzony czas.
Gdy w poszczególnych salkach odbywały się prezentacje, w holu głównym na stoiskach
wystawców moŜna było porozmawiać o prezentowanych produktach i usługach, poczęstować się
jakimś gratisem lub spróbować szczęścia w losowaniu nagrody rzeczowej. Wśród nagród była
m.in. konsola Wii, (na której przez trzy dni moŜna było zagrać w tenisa), przejaŜdŜka rajdowym
Porsche (ja musiałem się zadowolić wylosowanym kalendarzem) oraz iPod. Jednak najciekawszy
konkurs zorganizowała firma QuantiMetrics, wygrała ta osoba, która najdokładniej oszacowała
ilość kolorowych piłeczek znajdujących się w przezroczystej kuli. Warto wspomnieć równieŜ o
stoisku z ksiąŜkami, na którym moŜna było znaleźć naprawdę duŜy wybór literatury o testowaniu
i zarządzaniu jakością, w większości w jęz. niemieckim. Świadczy to w pewnym sensie o
wielkości niemieckiego rynku, w Polsce o takim wyborze póki co moŜemy chyba tylko pomarzyć.
śadna dobra konferencja nie moŜe odbyć się bez części mniej oficjalnej. Organizatorzy
konferencji stanęli na wysokości zadania i zaprosili uczestników do First Comfort Club na
pobliskim stadionie LTUarena. W sali klubowej umieszczonej przy jednej z trybun stadionu nie
moŜna było narzekać na brak jedzenia, napoi lub słabą obsługę. Wszystko było na najwyŜszym
poziomie. Jak przystało na imprezę sportową, bankiet rozpoczął się występem cheerleaderek,
natomiast dalszą część wieczoru umilał występ zespołu muzycznego.
Rysunek 4. First Comfort Club (fot. autora) Rysunek 5. LTUarena (fot. autora)
TESTER.PL
Strona 63 z 63
Gdy rozpoczynałem swoją przygodę z testowaniem, po kilku miesiącach zacząłem się
zastanawiać czy ta praca ma sens i czy nie szkoda mojego czasu. Programiści spóźniali się z
dostarczaniem iteracji, a jak dostarczali na czas to nic nie działało. A nawet, jeśli działało to
klikanie tego samego ileś razy pod rząd było takie nudne. Ale pojechałem na pierwszą
konferencję SJSI, tam poznałem innych testerów z innych firm i dowiedziałem się, Ŝe niektóre
rzeczy takie juŜ po prostu są. Dowiedziałem się równieŜ, Ŝe wiele rzeczy moŜna zmienić,
udoskonalić, zacząć od nowa. Teraz mając więcej doświadczenia wiele rzeczy mnie juŜ nie
dziwi, lecz nadal są takie, które mnie nudzą lub draŜnią. JednakŜe po konferencji w
Düsseldorfie mam więcej pomysłów by niektóre rzeczy zmienić na lepsze. I dlatego uwaŜam,
Ŝe to była udana konferencja, i uwaŜam, Ŝe na konferencje warto jeździć.