wtorek, 20 marca 2007

Szara skrzynka pełna plusów i minusów

Termin "szara skrzynka" pojawia się mniej lub bardziej formalnie na stronach książek, w internecie lub pismach branżowych. Z moich obserwacji nie istnieje żadna zestandaryzowana definicja tej techniki. To bardzo dobrze! Dla mnie oznacza to mniej więcej następujący proces:
  1. Analiza dostępnej dokumentacji i danych historycznych (jeśli istnieją)
    Wszelka dokumentacja zaczynając od wymagań, poprzez dokumenty techniczne a na rozmowach z architektami kończąc.
    Jeśli jest to kolejna wersja systemu lub projekt integracyjny to nie powinno być problemów z uzyskaniem takich danych. W przypadku nowego projektu, warto jest poczytać o podobnych rozwiązaniach.

  2. Weryfikacja statusu implementacji rozwiązania
    Jeśli faza kodowania jest bardzo wczesna to nie ma nawet sensu zaglądać do kodu bo zmieni się on jeszcze wiele razy. Warto natomiast obserwować rewizje komitowane do systemu kontroli wersji... mówi to bardzo dużo o łatwych i trudnych implementacyjnie obszarach

  3. "Przejście" po kodzie i zidentyfikowanie fragmentów ryzykownych
    Na tym etapie - jeśli oczywiście kod jest wystarczająco "dojrzały" - wystarczy po prostu przeglądać go i identyfikować takie elementy jak: "duże" w sensie linii kodu funkcje, nieuporządkowane fragmenty (gdzie stosuje się np. różne konwencje standardu kodowania), "dużo" wykomentowanego kodu, "dziwne" nazwy zmiennych, wartości wpisywane na stałe (tzw. hardkodowanie), itp. (Warto jest utrzymywać plik z listą kontrolną takich "gadżetów").

  4. Porównanie znalezisk z wymaganiami
    Należy dokładnie wiedzieć, jakich funkcjonalności dotyczą potencjalnie niebezpieczne obszary i w jaki sposób widoczne są w "runtime".

  5. Pierwsze podejście do testów - plan ogólny
    Spisanie sobie ogólnego planu zawierającego także wstępną listę przypadków testowych

  6. Analiza dokumentów z procesu produkcji oprogramowania
    Chodzi tutaj generalnie o analizę raportów z testów jednostkowych, inspekcji kodu, jak również obserwację częstotliwości komitów do repozytorium.

  7. Uszczegółowienie planu testów
    Dopisanie brakujących przypadków testowych.

  8. Dokładna analiza "trudnych" fragmentów
    Ten etap znajduje zastosowanie przeważnie w kolejnych cyklach testowania, kiedy okazuje się, że klasyczne podejście do testów jest niewystarczające. Chodzi o zidentyfikowanie - na podstawie defektów - obszarów najbardziej "zarobaczonych" i przyjrzenie się sposobowi w jaki jest on zaimplementowany w kodzie. Następnie należy zaprojektować przypadki testowe odpowiadającemu zastanemu stanowi. Najczęściej oznacza to duże obłożenie warunków brzegowych oraz zagęszczanie klas równoważności.

  9. Ponowne uszczegółowienie planu testów
Tak naprawdę to dotarcie do punktu nr. 5 daje bardzo duże efekty. Ale np. korzystanie z takiej dokumentacji jak raporty z testów jednostkowych lub protokoły z inspekcji kodu nadwyraz wydajnie pozwalają sprytnemu testerowi identyfikować groźne obszary (ale to temat na całą książkę) i wcale nie muszą być wykorzystywane w sekwencji przedstawionej powyżej.

Zastanawiając się na wadami i zaletami takiego podejścia, następujące punkty przyszły mi do głowy:

Plusy

  1. Testowanie czarną skrzynką opiera się na domniemaniu, że kod napisany jest zgodnie z zasadami inżynierii oprogramowania a praktyka pokazuje, że tak jest często ale nie zawsze i nie w pełnym zakresie.

  2. Termin "inżynieria oprogramowania" nie oznacza z punktu widzenia testów absolutnie nic. Przysłowiowe "Hello world" może być zakodowane w jednym języku na milion sposobów i każdy z nich będzie spełniał różne wymagania co pociąga za sobą różne podejścia przy projektowaniu testów.

  3. Analiza kodu pozwala na identyfikację potencjalnie ryzykownych miejsc. Oczywiście ma to swoje ograniczenia. W przypadku systemów czasu rzeczywistego nie zidentyfikuje się w ten sposób defektów związanych z zależnościami czasowymi ale na pewno pozwoli zaoszczędzić czas na "walcowaniu" całości poprzez większy nacisk na miejsca ryzykowne.

  4. Pozwoli inżynierowi do spraw testów zrozumieć architekturę samego rozwiązania (z mojego doświadczenia wynika, iż wewnętrzne szkolenia poświęcone implementowanej architekturze są naprawdę rzadkością!?) co w sposób znakomity usprawnia proces projektowania testów poprzez uprzednie dostarczenie wiedzy na temat wysokopoziomowej struktury testowanego rozwiązania.

  5. Nie ma konieczności czytania całego kodu. Ponieważ nie sprawdzamy poprawności działania każdej struktury/obiektu/klasy czy usługi. Na potrzeby testów behawioralnych potrzebne są nam fragmenty przetwarzające logikę biznesową.

  6. W sytuacji gdy zmuszeni jesteśmy zatrudniać ludzi, którzy testowanie widzą jedynie jako etap pozwalający przejść do programowania, może być to doskonałe narzędzie do wykorzystania ich potencjału jak również motywowania.

  7. Eliminuje ryzyko testowania rozwiązania wbrew jego logice. To znaczy gdy nasze przypuszczenia co do implementacji są drastyczne różne od założeń implementatora. To ryzyko może być groźne w sytuacji kiedy mamy czas tylko na pobieżne testy w celu określenia jak bardzo jest dany obszar niebezpieczny. Po testach dymnych może wyglądać, że rozwiązanie działa dobrze a w środowisku rzeczywistym pojawi się katastrofa.

Minusy

  1. Praca nad kodem może łatwo przerodzić się w zabawę z kodem trwającą bez końca. Może to prowadzić do kompletnej indolencji testowej przy jednoczesnym ogromnym obłożeniu zespołu pracą

  2. Kod bardzo często jest w postaci sote a wiec bez komentarzy. Dodatkowo, jeśli w danym środowisku wykorzystuje się komponenty dostawców zewnętrznych, komponenty generyczne lub inne kompleksy integrowane, których implementacja poprzez interfejs jest skomplikowana to czytanie takiego kodu staje się niemożliwe bez głębszej wiedzy.
    Ten problem jest częściowo niwelowany przez "Plus" nr. 5

  3. Osoby zatrudniane na stanowisko testera często nie posiadają kompetencji rozumienia kodu - "bo przecież nie potrzeba". Ale zawsze w zespole testowym znajdzie się osoba, która trochę programowała lub ma zacięcie w tym kierunku. Należy to wykorzystać, zlecając jej analizę kodu pod względem identyfikacji potencjalnych ryzyk. Czasami wystarczą pobieżne oględziny i odrazu widać miejsca, z którymi programista strasznie ciężko walczył. Pomocą tutaj mogą być raporty z przeglądu kodu - jeśli takie praktyki są prowadzone.

  4. Rozpoczęcie projektowania testów jest możliwe tylko gdy faza kodowania jest mocno rozwinięta i można korzystać zarówno z kodu jak i z raportu o zmianach wersji (co często bywa pomocne przy identyfikowaniu "kłopotliwych" obszarów).

  5. Istotnym ograniczenie jest znajomość języków. Jeśli trafimy na projekt napisany w zupełnie obcej nam technologii to nie jesteśmy w stanie efektywnie korzystać z tej techniki.
Powyższy opis procesu nie stanowi całości ale to chyba punkty, które mnie najbardziej interesują i których usystematyzowania odczuwałem potrzebę.

Brak komentarzy: