Lekcja 4.2: Techniki Czarnoskrzynkowe

W poprzedniej lekcji poznaliśmy trzy główne kategorie technik projektowania testów.

Teraz zagłębimy się w pierwszą z nich – techniki czarnoskrzynkowe.

Przypomnijmy: skupiają się one na zewnętrznym zachowaniu systemu, bazując na specyfikacji i wymaganiach, a ignorując wewnętrzną strukturę kodu.

Są to jedne z najczęściej stosowanych technik w codziennej pracy testera.

Sylabus ISTQB Foundation Level v4.0 w sekcji 4.2 (FL-4.2.1 K3, FL-4.2.2 K3, FL-4.2.3 K3, FL-4.2.4 K3) wymaga od nas nie tylko zrozumienia, ale i umiejętności praktycznego zastosowania czterech kluczowych technik czarnoskrzynkowych.

Są to:

  1. Podział na klasy równoważności (Equivalence Partitioning - EP)
  2. Analiza wartości brzegowych (Boundary Value Analysis - BVA)
  3. Testowanie w oparciu o tablicę decyzyjną (Decision Table Testing)
  4. Testowanie przejść pomiędzy stanami (State Transition Testing)

W tej lekcji szczegółowo omówimy każdą z tych technik, wyjaśnimy ich założenia, pokażemy, jak je stosować w praktyce na przykładach, oraz wskażemy, jakie korzyści przynoszą i jakie mają ograniczenia.

1. Podział na Klasy Równoważności (Equivalence Partitioning - EP)

Cel: Zredukowanie liczby przypadków testowych do zarządzalnego minimum, przy jednoczesnym zachowaniu rozsądnego pokrycia możliwych danych wejściowych i wyjściowych.

Założenie: Dane wejściowe (lub wyjściowe) systemu można podzielić na grupy (klasy równoważności), w których wszystkie elementy są traktowane przez system w ten sam sposób.

Jeśli test dla jednego elementu z klasy wykryje błąd, to testy dla innych elementów z tej samej klasy prawdopodobnie również go wykryją.

I odwrotnie – jeśli test dla jednego elementu przejdzie pomyślnie, inne elementy z tej klasy również powinny.

Jak stosować?

  1. Zidentyfikuj parametry wejściowe i wyjściowe: Przeanalizuj specyfikację, aby znaleźć wszystkie dane, które system przyjmuje lub generuje (np. pola formularzy, parametry API, komunikaty).
  2. Określ warunki dla każdego parametru: Zastanów się, jakie reguły lub ograniczenia dotyczą każdego parametru (np. typ danych, zakres wartości, dozwolone znaki, format).
  3. Podziel dane na klasy równoważności: Dla każdego parametru utwórz co najmniej dwie grupy:
    • Poprawne klasy równoważności (Valid Equivalence Partitions): Zawierają wartości, które system powinien zaakceptować i przetworzyć zgodnie ze specyfikacją.
    • Niepoprawne klasy równoważności (Invalid Equivalence Partitions): Zawierają wartości, które system powinien odrzucić, zignorować lub obsłużyć jako błąd (np. wartości spoza zakresu, nieprawidłowy format, niedozwolone znaki).
    Staraj się, aby klasy były rozłączne (nie miały wspólnych elementów) i pokrywały cały możliwy zakres danych dla danego parametru.
  4. Wybierz wartości testowe: Z każdej zidentyfikowanej klasy równoważności wybierz co najmniej jedną reprezentatywną wartość do przetestowania.
  5. Zaprojektuj przypadki testowe: Stwórz przypadki testowe, które używają wybranych wartości. Zazwyczaj dąży się do pokrycia jak największej liczby poprawnych klas w jednym przypadku testowym, ale każdą niepoprawną klasę testuje się osobno, aby uniknąć maskowania błędów (sytuacji, gdy jeden błąd uniemożliwia wykrycie innego).

Przykład: Pole do wprowadzania wieku użytkownika, które akceptuje liczby całkowite od 18 do 65.

  • Poprawne klasy równoważności:
    • Liczby całkowite od 18 do 65 (np. wybieramy 30)
  • Niepoprawne klasy równoważności:
    • Liczby całkowite mniejsze niż 18 (np. wybieramy 17)
    • Liczby całkowite większe niż 65 (np. wybieramy 66)
    • Wartości niebędące liczbami całkowitymi (np. 25.5, "abc", puste pole)

Przypadki testowe:

  1. Wprowadź wiek 30 (oczekiwany rezultat: akceptacja).
  2. Wprowadź wiek 17 (oczekiwany rezultat: odrzucenie/błąd).
  3. Wprowadź wiek 66 (oczekiwany rezultat: odrzucenie/błąd).
  4. Wprowadź wiek 25.5 (oczekiwany rezultat: odrzucenie/błąd).
  5. Wprowadź "abc" (oczekiwany rezultat: odrzucenie/błąd).
  6. Pozostaw pole puste (oczekiwany rezultat: odrzucenie/błąd, jeśli pole jest wymagane).

Pokrycie: Celem jest pokrycie 100% zidentyfikowanych klas równoważności (każda klasa testowana co najmniej raz).

Mierzy się je jako (liczba przetestowanych klas / całkowita liczba klas) * 100%.

Korzyści: Znacząca redukcja liczby testów, systematyczne podejście do wyboru danych testowych.

Ograniczenia: Nie uwzględnia interakcji między różnymi parametrami wejściowymi; zakłada, że wszystkie wartości w klasie są traktowane identycznie, co nie zawsze jest prawdą, szczególnie blisko granic.

2. Analiza Wartości Brzegowych (Boundary Value Analysis - BVA)

Cel: Uzupełnienie podziału na klasy równoważności poprzez skupienie się na wartościach granicznych (brzegowych) tych klas.

Założenie: Doświadczenie pokazuje, że błędy programistyczne często występują na granicach klas równoważności (np. przy porównaniach typu >, <, >=, <=).

BVA koncentruje się na testowaniu tych właśnie „krawędzi”.

Jak stosować?

  1. Zidentyfikuj klasy równoważności: Wykonaj podział na klasy równoważności (EP) jak opisano powyżej. Interesują nas głównie klasy z uporządkowanymi wartościami (np. liczby, daty, zakresy znaków).
  2. Zidentyfikuj granice: Dla każdej uporządkowanej klasy równoważności (zarówno poprawnej, jak i niepoprawnej) zidentyfikuj jej wartości graniczne (minimalną i maksymalną wartość w klasie).
  3. Wybierz wartości testowe: Istnieją dwa główne podejścia:
    • BVA dwuwartościowe (Two-value BVA): Dla każdej granicy wybierz dwie wartości: samą wartość graniczną i wartość tuż obok niej po drugiej stronie granicy (np. jeśli granica to 18, testuj 17 i 18).
    • BVA trójwartościowe (Three-value BVA): Dla każdej granicy wybierz trzy wartości: wartość tuż przed granicą, samą granicę i wartość tuż za granicą (np. jeśli granica to 18, testuj 17, 18 i 19). Jest to podejście bardziej dokładne i częściej zalecane.
  4. Zaprojektuj przypadki testowe: Stwórz przypadki testowe używające wybranych wartości brzegowych. Podobnie jak w EP, testuj niepoprawne wartości brzegowe osobno.

Przykład (kontynuacja pola wieku 18-65):

Granice to 18 i 65.

Wartości testowe dla BVA trójwartościowego:

  • Dolna granica (18): Testuj 17 (niepoprawna), 18 (poprawna), 19 (poprawna).
  • Górna granica (65): Testuj 64 (poprawna), 65 (poprawna), 66 (niepoprawna).

Przypadki testowe (uzupełniające EP):

  1. Wprowadź wiek 18 (oczekiwany rezultat: akceptacja).
  2. Wprowadź wiek 19 (oczekiwany rezultat: akceptacja).
  3. Wprowadź wiek 64 (oczekiwany rezultat: akceptacja).
  4. Wprowadź wiek 65 (oczekiwany rezultat: akceptacja).
  5. (Wartości 17 i 66 były już w EP).

Pokrycie: Celem jest pokrycie 100% zidentyfikowanych wartości brzegowych. Mierzy się je jako (liczba przetestowanych wartości brzegowych / całkowita liczba wartości brzegowych) * 100%.

Korzyści: Skuteczne wykrywanie błędów związanych z obsługą granic zakresów, uzupełnia EP.

Ograniczenia: Nadal nie uwzględnia kombinacji parametrów; zakłada, że granice są dobrze zdefiniowane.

3. Testowanie w Oparciu o Tablicę Decyzyjną (Decision Table Testing)

Cel: Systematyczne testowanie złożonych reguł biznesowych, które zależą od kombinacji różnych warunków wejściowych.

Założenie: Logikę biznesową można przedstawić w formie tabeli, gdzie kolumny reprezentują warunki (wejścia) i akcje (wyjścia/zachowania), a wiersze reprezentują reguły (kombinacje warunków prowadzące do określonych akcji).

Jak stosować?

  1. Zidentyfikuj warunki i akcje: Przeanalizuj specyfikację, aby znaleźć wszystkie warunki (zazwyczaj logiczne, np. Tak/Nie, Prawda/Fałsz), które wpływają na decyzje systemu, oraz wszystkie możliwe akcje, które system może podjąć w odpowiedzi.
  2. Stwórz szkielet tabeli: Narysuj tabelę. W górnej części umieść wiersze dla warunków, a w dolnej dla akcji.
  3. Określ możliwe kombinacje warunków: Wypełnij kolumny tabeli wszystkimi możliwymi kombinacjami wartości warunków (np. dla N warunków binarnych będzie 2^N kombinacji). Każda kolumna reprezentuje jedną regułę.
  4. Określ akcje dla każdej reguły: Dla każdej kolumny (reguły) określ, jakie akcje powinny zostać wykonane, gdy dana kombinacja warunków jest spełniona. Oznacz odpowiednie pola w sekcji akcji (np. 'X' lub '✓').
  5. Uprość tabelę (opcjonalnie): Czasami można połączyć kolumny (reguły), które mają te same akcje, a różnią się tylko w warunkach, które nie wpływają na wynik (oznaczane jako '-' lub 'N/A' - nie dotyczy).
  6. Zaprojektuj przypadki testowe: Każdą kolumnę (regułę) w (potencjalnie uproszczonej) tabeli decyzyjnej przekształć w co najmniej jeden przypadek testowy. Przypadek testowy powinien realizować daną kombinację warunków i weryfikować, czy system wykonuje oczekiwane akcje.

Przykład: Logowanie do systemu. Warunki: Poprawny login (T/F), Poprawne hasło (T/F). Akcje: Zaloguj (X), Wyświetl błąd (X).

| Warunki | Reguła 1 | Reguła 2 | Reguła 3 | Reguła 4 |

|----------------|----------|----------|----------|----------|

| Poprawny login | T | T | F | F |

| Poprawne hasło | T | F | T | F |

|----------------|----------|----------|----------|----------|

| Akcje | | | | |

| Zaloguj | X | | | |

| Wyświetl błąd | | X | X | X |

Przypadki testowe:

  1. Podaj poprawny login i poprawne hasło (oczekiwane: zalogowanie).
  2. Podaj poprawny login i niepoprawne hasło (oczekiwane: błąd).
  3. Podaj niepoprawny login i poprawne hasło (oczekiwane: błąd).
  4. Podaj niepoprawny login i niepoprawne hasło (oczekiwane: błąd).

Pokrycie: Celem jest pokrycie 100% reguł w tabeli decyzyjnej. Mierzy się je jako (liczba przetestowanych reguł / całkowita liczba reguł) * 100%.

Korzyści: Systematyczne podejście do testowania złożonej logiki, pomaga zidentyfikować brakujące lub sprzeczne reguły.

Ograniczenia: Liczba reguł rośnie wykładniczo wraz z liczbą warunków, co może prowadzić do bardzo dużych tabel; trudne do zastosowania, gdy warunki nie są binarne lub gdy kolejność ma znaczenie.

4. Testowanie Przejść Pomiędzy Stanami (State Transition Testing)

Cel: Testowanie systemów, których zachowanie zależy od bieżącego stanu i zdarzeń, które mogą ten stan zmienić.

Założenie: System można zamodelować jako maszynę stanów skończonych (Finite State Machine), która przechodzi między różnymi stanami w odpowiedzi na określone zdarzenia (wyzwalacze). Przejście może być powiązane z wykonaniem określonej akcji.

Jak stosować?

  1. Zidentyfikuj stany: Określ wszystkie możliwe, rozłączne stany, w jakich może znajdować się system lub jego komponent (np. Włączony, Wyłączony, Zablokowany, Oczekujący).
  2. Zidentyfikuj zdarzenia (wyzwalacze): Określ zdarzenia, które mogą powodować przejścia między stanami (np. Naciśnięcie przycisku, Otrzymanie komunikatu, Upłynięcie czasu, Wprowadzenie danych).
  3. Zidentyfikuj przejścia: Określ, które zdarzenia powodują przejścia z których stanów do których stanów.
  4. Zidentyfikuj akcje (opcjonalnie): Określ akcje wykonywane podczas przejść lub w poszczególnych stanach.
  5. Stwórz model stanu: Narysuj diagram stanów (graf, gdzie węzły to stany, a krawędzie to przejścia oznaczone zdarzeniami/akcjami) lub tabelę przejść stanów (macierz, gdzie wiersze to stany, kolumny to zdarzenia, a komórki pokazują stan docelowy i akcję).
  6. Zaprojektuj przypadki testowe: Celem jest pokrycie różnych elementów modelu. Typowe poziomy pokrycia:
    • Pokrycie stanów (All states coverage): Zaprojektuj testy tak, aby odwiedzić każdy stan co najmniej raz (najsłabsze pokrycie).
    • Pokrycie przejść (All transitions coverage / 0-switch coverage): Zaprojektuj testy tak, aby wykonać każde możliwe przejście co najmniej raz (częściej stosowane).
    • Pokrycie sekwencji przejść (n-switch coverage): Zaprojektuj testy tak, aby pokryć sekwencje n kolejnych przejść (bardziej zaawansowane).
    Przypadki testowe często opisują sekwencje zdarzeń prowadzące do określonych przejść i weryfikujące oczekiwane stany końcowe oraz akcje.

Przykład: Prosty PIN (3 próby). Stany: Oczekujący na PIN, Zablokowany. Zdarzenia: Wprowadź poprawny PIN, Wprowadź niepoprawny PIN.

Diagram/Tabela:

- Ze stanu 'Oczekujący':

- Zdarzenie 'Poprawny PIN' -> Przejście do stanu 'Odblokowany' (Akcja: Zezwól na dostęp)

- Zdarzenie 'Niepoprawny PIN' (próba 1, 2) -> Pozostaje w stanie 'Oczekujący' (Akcja: Zmniejsz licznik prób)

- Zdarzenie 'Niepoprawny PIN' (próba 3) -> Przejście do stanu 'Zablokowany' (Akcja: Wyświetl komunikat o blokadzie)

- Ze stanu 'Zablokowany':

- Brak przejść (lub np. zdarzenie 'Odblokuj przez administratora')

Przypadki testowe (dla pokrycia przejść):

  1. Start -> Wprowadź poprawny PIN (Testuje przejście Oczekujący -> Odblokowany).
  2. Start -> Wprowadź niepoprawny PIN (Testuje przejście Oczekujący -> Oczekujący, próba 1).
  3. Start -> Niepoprawny PIN -> Niepoprawny PIN (Testuje przejście Oczekujący -> Oczekujący, próba 2).
  4. Start -> Niepoprawny PIN -> Niepoprawny PIN -> Niepoprawny PIN (Testuje przejście Oczekujący -> Zablokowany).

Pokrycie: Celem jest pokrycie 100% stanów lub (częściej) 100% przejść. Mierzy się je jako (liczba przetestowanych stanów/przejść / całkowita liczba stanów/przejść) * 100%.

Korzyści: Skuteczne w testowaniu systemów sterowanych zdarzeniami, pomaga wizualizować i zrozumieć zachowanie systemu, wykrywa błędy związane z nieprawidłowymi lub brakującymi przejściami.

Ograniczenia: Przydatne tylko dla systemów, które mają wyraźne stany; modelowanie złożonych systemów może być trudne i czasochłonne.

Podsumowanie

Techniki czarnoskrzynkowe są fundamentalnym narzędziem w arsenale testera.

Podział na klasy równoważności i analiza wartości brzegowych pomagają efektywnie testować dane wejściowe i wyjściowe.

Tablice decyzyjne pozwalają systematycznie weryfikować złożone reguły biznesowe.

Testowanie przejść między stanami jest idealne dla systemów sterowanych zdarzeniami.

Umiejętność wyboru i zastosowania odpowiedniej techniki (lub ich kombinacji) w zależności od kontekstu jest kluczowa dla skutecznego testowania.

Najczęściej Zadawane Pytania (FAQ)

Czy zawsze trzeba stosować BVA razem z EP?
Zdecydowanie zalecane. EP redukuje liczbę testów, ale BVA skupia się na obszarach (granicach), gdzie błędy są najbardziej prawdopodobne. Stosowanie obu technik razem daje znacznie lepsze pokrycie niż każda z nich osobno.
Jak radzić sobie z bardzo dużą liczbą reguł w tabeli decyzyjnej?
Można spróbować uprościć tabelę, łącząc reguły z tymi samymi akcjami. Jeśli tabela nadal jest zbyt duża, można priorytetyzować reguły (np. testować tylko te najbardziej prawdopodobne lub ryzykowne) lub rozważyć inne techniki.
Czy testowanie przejść między stanami nadaje się do testowania GUI?
Tak, jeśli interfejs użytkownika ma wyraźne stany (np. różne ekrany, aktywne/nieaktywne przyciski w zależności od kontekstu). Można modelować nawigację między ekranami lub zmiany stanu kontrolek jako przejścia wyzwalane akcjami użytkownika.
Co jeśli specyfikacja jest niejasna lub niekompletna?
Techniki czarnoskrzynkowe opierają się na specyfikacji. Jeśli jest ona słaba, należy najpierw dążyć do jej wyjaśnienia lub uzupełnienia. W międzyczasie można wspomagać się technikami opartymi na doświadczeniu lub próbować wyprowadzić klasy/stany z istniejącego systemu.
Czy te techniki można stosować do testów niefunkcjonalnych?
Głównie dotyczą testów funkcjonalnych. Jednak niektóre aspekty można zaadaptować, np. EP/BVA do testowania wydajności przy różnych obciążeniach (granice wydajności) lub testowanie stanów do weryfikacji obsługi błędów (stany błędów).
Ile wartości wybrać z każdej klasy równoważności?
Teoretycznie wystarczy jedna wartość, ponieważ zakładamy, że wszystkie działają tak samo. W praktyce, dla ważnych klas, można wybrać więcej niż jedną wartość (np. blisko środka zakresu), aby zwiększyć pewność.
Czym różni się BVA dwuwartościowe od trójwartościowego?
Dwuwartościowe testuje granicę i wartość tuż za nią (po drugiej stronie). Trójwartościowe testuje wartość tuż przed, samą granicę i wartość tuż za nią. Trójwartościowe jest bardziej dokładne, szczególnie przy błędach typu "off-by-one".
Czy tablica decyzyjna zawsze musi zawierać wszystkie 2^N kombinacji?
Pełna tabela zawiera wszystkie kombinacje, co gwarantuje kompletność analizy. Jednak jeśli niektóre kombinacje są niemożliwe lub nieistotne biznesowo, można je pominąć lub uprościć tabelę, ale należy to robić świadomie.
Jakie narzędzia wspierają modelowanie stanów?
Istnieją narzędzia do rysowania diagramów UML (które obejmują diagramy stanów), a także specjalistyczne narzędzia do modelowania i generowania testów z modeli stanów. Nawet proste narzędzia do rysowania diagramów mogą być pomocne.
Czy można łączyć testowanie przejść stanów z tablicami decyzyjnymi?
Tak, czasami warunki wyzwalające przejście między stanami są złożone i zależą od kombinacji innych czynników. W takim przypadku logikę decyzyjną wewnątrz przejścia można zamodelować i przetestować za pomocą tablicy decyzyjnej.

Przykładowe Pytania Egzaminacyjne

Pytanie 1 (K3): System oblicza prowizję. Dla sprzedaży do 1000 zł prowizja wynosi 10%. Dla sprzedaży powyżej 1000 zł do 5000 zł włącznie, prowizja wynosi 15%. Dla sprzedaży powyżej 5000 zł prowizja wynosi 20%. Używając analizy wartości brzegowych (BVA trójwartościowej), które wartości sprzedaży należy przetestować?

  • a) 0, 1000, 5000
  • b) 999, 1000, 1001, 4999, 5000, 5001
  • c) 10, 15, 20
  • d) 500, 3000, 6000

Poprawna odpowiedź: b (Granice to 1000 i 5000. BVA trójwartościowe wymaga testowania wartości tuż przed, na i tuż za granicą: 999/1000/1001 oraz 4999/5000/5001.)

Pytanie 2 (K3): Analizujesz system rezerwacji biletów lotniczych. Warunki: Czy pasażer jest członkiem klubu lojalnościowego (T/F)? Czy rezerwacja jest dokonywana z wyprzedzeniem > 14 dni (T/F)? Akcje: Zastosuj zniżkę 10% (X), Zastosuj zniżkę 5% (X), Brak zniżki (X). Która technika jest najbardziej odpowiednia do systematycznego przetestowania tych reguł?

  • a) Analiza wartości brzegowych
  • b) Testowanie przejść między stanami
  • c) Podział na klasy równoważności
  • d) Testowanie w oparciu o tablicę decyzyjną

Poprawna odpowiedź: d (Mamy tu do czynienia z kombinacją warunków logicznych prowadzących do różnych akcji, co jest idealnym scenariuszem dla tablicy decyzyjnej.)

Pytanie 3 (K2): Jaka jest główna zaleta podziału na klasy równoważności?

  • a) Gwarantuje znalezienie wszystkich błędów.
  • b) Pozwala zredukować liczbę potrzebnych przypadków testowych.
  • c) Testuje interakcje między różnymi parametrami wejściowymi.
  • d) Skupia się na wewnętrznej strukturze kodu.

Poprawna odpowiedź: b (Głównym celem EP jest optymalizacja testowania poprzez wybór reprezentatywnych wartości z każdej klasy, co znacząco redukuje liczbę testów w porównaniu do testowania wszystkich możliwych wartości.)