Podręcznik

1. Podstawy testowania oprogramowania

1.2. Poziomy testowania

W procesie tworzenia oprogramowania testowanie nie jest jednolitym zadaniem, lecz składa się z wielu warstw, każda z nich odpowiada za różne aspekty i etapy weryfikacji produktu. Niniejszy rozdział przedstawia szczegółowy przegląd czterech głównych poziomów testowania, które są niezbędne do zapewnienia jakości i efektywności współczesnego oprogramowania. Te poziomy obejmują:

Testy Jednostkowe: Pierwsza linia obrony przed błędami, koncentrująca się na najmniejszych jednostkach kodu.

Testy Integracyjne: Sprawdzają interakcje między zintegrowanymi komponentami, ujawniając problemy, które nie były widoczne podczas testów jednostkowych.

Testy Systemowe: Przeprowadzane są na kompletnym systemie, aby zweryfikować, że wszystkie komponenty współpracują harmonijnie, dostarczając wymaganej funkcjonalności na poziomie systemowym.

Testy Akceptacyjne: Ostateczna weryfikacja przed wypuszczeniem produktu na rynek, zapewniająca, że oprogramowanie spełnia oczekiwania użytkowników końcowych i biznesowe wymogi.


Każdy poziom jest kluczowy w cyklu życia oprogramowania i odgrywa unikalną rolę w dostarczaniu wartości dla klienta i użytkowników. W kolejnych sekcjach omówione zostanie , jak każdy poziom przyczynia się do sukcesu projektu, jakie narzędzia są najbardziej efektywne, a także wyzwania i najlepsze praktyki związane z każdym etapem testowania. Przedstawione zostaną również przykładowe scenariusze sukcesów i porażek, które posłużą jako cenne lekcje dla deweloperów i testerów oprogramowania.

1.2.1 Testy Jednostkowe (Unit Testing)

Przed opisaniem testów jednostkowych należy zając się terminem "jednostka" wymagającym dodatkowego wyjaśnienia. Istnieje kilka interpretacji na temat tego, co dokładnie co stanowi jednostkę. W proceduralnym języku programowania, jednostką może być:

  • pojedyncza procedura,

  • funkcja,

  • ciało kodu, które implementuje pojedynczą funkcję,

  • kod źródłowy, który mieści się na jednej stronie,

  • ciało kodu, które reprezentuje pracę wykonaną w określonym czasie,

  • najmniejszy fragment kodu, który może być skompilowany samodzielnie.

W obiektowym języku programowania istnieje ogólna zgoda, że klasa jest jednostką. Jednakże metody klasy mogą być opisane przez którąkolwiek z powyższych "definicji" jednostki dla języka programowania proceduralnego.

Wniosek jest taki, że "jednostka" jest prawdopodobnie najlepiej zdefiniowana przez twórcę kodu - najczęściej programistę. Może być również zdefiniowana w zasadach ogólnych zespołu programistycznego i wtedy taką część kodu uważamy za jednostkę.

Z punktu widzenia testów należy założyć, że jednostką jest fragment oprogramowania który został zaprojektowany oraz napisany przez jedną osobę i przez ta osoba będzie go testowała.

Testy jednostkowe koncentrują się na indywidualnych komponentach oprogramowania, takich jak funkcje, metody lub klasy. Są to testy izolowane, co oznacza, że każdy testowany element jest sprawdzany niezależnie od innych. Celem testów jednostkowych jest weryfikacja, czy poszczególne jednostki działają poprawnie w izolacji.

Scenariusze Testowe: Scenariusz testowy dla funkcji obliczającej VAT może wyglądać następująco:

  • Przypadek testowy 1:

    Podstawowa stawka VAT.

    • Wejście: Kwota netto 100, stawka VAT 23%.

    • Oczekiwane wyjście: Kwota VAT 23.

  • Przypadek testowy 2:

    Stawka VAT zwolniona.

    • Wejście: Kwota netto 100, stawka VAT 0%.

    • Oczekiwane wyjście: Kwota VAT 0.

Narzędzia:

  • Jest dla JavaScript: Framework testowy zapewniający prostotę i szybkość wykonania testów.

  • JUnit dla Javy: Popularne narzędzie do automatyzacji testów jednostkowych w środowisku JVM.

  • Mockito dla Javy: Umożliwia tworzenie obiektów mockowych do izolowania testowanych komponentów.

Wyzwania i Najlepsze Praktyki:

  • Wyzwanie: Utrzymanie izolacji testów może być trudne, gdy komponenty są silnie powiązane.

  • Najlepsza praktyka: Używanie technik mockowania i iniekcji zależności do minimalizowania zależności między testowanymi komponentami.

Przykłady Sukcesów i Niepowodzeń:

  • Sukces: Użycie TDD w rozwoju nowej funkcji pozwoliło na szybkie wykrycie i naprawę błędów, skutkując stabilnym wypuszczeniem produktu.

  • Niepowodzenie: Brak odpowiednich testów jednostkowych dla funkcji przeliczającej waluty doprowadził do niewykrycia błędu zaokrągleń, co miało wpływ na błędne faktury klientów.

Testy jednostkowe są fundamentem jakości kodu w procesie deweloperskim. Przeprowadzane na wczesnym etapie rozwoju oprogramowania, pozwalają na szybką i skuteczną weryfikację logiczną poszczególnych jednostek kodu. Jest to również pierwszy krok w kierunku budowy solidnej architektury oprogramowania, która będzie odporna na błędy i łatwa w utrzymaniu. Przyjęcie TDD może wydłużyć czas niezbędny do rozpoczęcia implementacji, ale w dłuższej perspektywie czasowej pozwala na oszczędność czasu i zasobów dzięki redukcji liczby defektów w oprogramowaniu.

1.2.2 Testy Integracyjne (Integration Testing)

Testy integracyjne oceniają współpracę i komunikację między zintegrowanymi komponentami oprogramowania, takimi jak moduły, klasy, funkcje, czy całe usługi. Głównym celem jest identyfikacja problemów, które mogą wystąpić gdy oddzielnie testowane jednostki są połączone w jeden system. Testy te sprawdzają poprawność interfejsów, zgodność danych, oraz współpracę funkcji w złożonym środowisku.

Scenariusze Testowe: Dla systemu zarządzania zamówieniami scenariusze mogą obejmować:

  • Przypadek testowy 1: Przepływ danych między modułem koszyka a systemem płatności.

    • Wejście: Wprowadzenie danych kart kredytowych i potwierdzenie zakupu.

    • Oczekiwane wyjście: Poprawne przekazanie danych do systemu płatności i zainicjowanie transakcji.

  • Przypadek testowy 2: Integracja modułu wysyłkowego z modułem zarządzania zamówieniami.

    • Wejście: Status zamówienia zmieniony na "gotowe do wysyłki".

    • Oczekiwane wyjście: Poprawne wygenerowanie listu przewozowego.

Narzędzia:

  • Postman dla API: Pozwala na testowanie i debugowanie API przez wysyłanie zapytań i analizowanie odpowiedzi.

  • Selenium dla UI: Automatyzuje przeglądarki internetowe, umożliwiając testowanie integracji interfejsu użytkownika z logiką biznesową.

  • Jenkins dla CI/CD: Automatyzuje procesy budowania i testowania, wspierając ciągłą integrację komponentów.

Wyzwania i Najlepsze Praktyki:

  • Wyzwanie: Zapewnienie kompatybilności i spójności danych między modułami, które były rozwijane niezależnie.

  • Najlepsza praktyka: Wczesne planowanie i definiowanie jasnych interfejsów i kontraktów między modułami; regularne przeprowadzanie testów integracyjnych w procesie rozwoju.

Przykłady Sukcesów i Niepowodzeń:

  • Sukces: Skuteczne wdrożenie testów integracyjnych umożliwiło szybką identyfikację i naprawę problemów komunikacyjnych między nowym API a istniejącą bazą danych, co zapobiegło przerwom w działaniu systemu w produkcji.

  • Niepowodzenie: Brak kompleksowych testów integracyjnych dla systemu e-commerce doprowadził do niezgodności w przepływie zamówień, co skutkowało przestojami i utratą dochodów.

Testy integracyjne są kluczowym elementem zapewnienia wysokiej jakości oprogramowania. Pozwalają nie tylko wykryć problemy na poziomie współdziałania komponentów, ale również sprawdzają, czy cały system jest gotowy do dalszych etapów testów, takich jak testy systemowe czy akceptacyjne. Aby maksymalizować efektywność testów integracyjnych, zaleca się ich automatyzację, co pozwala na częste i powtarzalne ich wykonanie, a także zapewnia szybką informację zwrotną o stanie systemu po wprowadzeniu zmian w kodzie. Implementacja ciągłej integracji (CI) i ciągłego wdrażania (CD) może znacznie usprawnić ten proces, zapewniając, że wszystkie komponenty systemu są regularnie testowane i gotowe do produkcji.

1.2.3 Testy Systemowe (System Testing)

Testy systemowe to proces weryfikacji kompletnego i zintegrowanego systemu informatycznego w celu zapewnienia, że spełnia on wszystkie zdefiniowane wymagania. Są one przeprowadzane w środowisku symulującym rzeczywistą eksploatację, co obejmuje nie tylko oprogramowanie, ale również sprzęt komputerowy oraz interakcje z użytkownikami i innymi systemami. Cel testów systemowych jest wielowymiarowy – nie tylko sprawdzają poprawność funkcjonalną i niefunkcjonalną systemu, ale również identyfikują błędy, które nie zostały wykryte na wcześniejszych etapach testów.

Scenariusze Testowe: Przykładowe scenariusze dla systemu rezerwacji biletów mogą wyglądać następująco:

  • Przypadek testowy 1: Rezerwacja biletu przez użytkownika.

    • Wejście: Użytkownik wprowadza datę, wybiera lot i dokonuje płatności.

    • Oczekiwane wyjście: System rejestruje rezerwację, przetwarza płatność i wysyła potwierdzenie.

  • Przypadek testowy 2: Anulowanie rezerwacji i zwrot kosztów.

    • Wejście: Użytkownik anuluje bilet co najmniej 24 godziny przed lotem.

    • Oczekiwane wyjście: System anuluje rezerwację i inicjuje proces zwrotu kosztów.

Narzędzia:

  • LoadRunner lub JMeter: Narzędzia do testowania wydajności i obciążenia, które pomagają w ocenie, jak system zachowuje się pod dużym obciążeniem.

  • Selenium WebDriver: Automatyzuje testy funkcjonalne interfejsu użytkownika w różnych przeglądarkach i systemach operacyjnych.

  • QTP (QuickTest Professional): Narzędzie do zautomatyzowanych testów funkcjonalnych, które wspiera różne środowiska aplikacji.

Wyzwania i Najlepsze Praktyki:

  • Wyzwanie: Złożoność środowiska testowego i konieczność symulacji rzeczywistych warunków użytkowania, w tym integracji z zewnętrznymi systemami.

  • Najlepsza praktyka: Stworzenie dedykowanego środowiska testowego, które naśladuje produkcyjne warunki użytkowania, w tym dane, obciążenie oraz integracje zewnętrzne.

Metody:

  • Black Box Testing: Testowanie bez znajomości wewnętrznej struktury systemu.

  • Performance Testing: Ocena wydajności systemu pod dużym obciążeniem.

Przykłady:

  • Sprawdzenie działania aplikacji e-commerce podczas symulacji ruchu użytkowników.

  • Testy bezpieczeństwa systemu bankowości internetowej.

Przykłady Sukcesów i Niepowodzeń:

  • Sukces: System ERP przeszedł kompleksowe testy systemowe, co pozwoliło na wychwycenie i naprawienie błędów związanych z przetwarzaniem danych, zanim system został wdrożony w organizacji.

  • Niepowodzenie: Niewystarczające testy systemowe aplikacji mobilnej doprowadziły do niewykrycia błędu w module geolokalizacji, co wpłynęło na negatywne doświadczenia użytkowników i konieczność szybkiego wydania poprawki.

Testy systemowe są niezbędne do potwierdzenia, że złożony system jako całość działa zgodnie z oczekiwaniami i jest gotowy do wdrożenia. Powinny obejmować różne aspekty systemu, takie jak funkcjonalność, bezpieczeństwo, wydajność, skalowalność i interoperacyjność. Ważnym aspektem jest również zapewnienie, że testy systemowe są powtarzalne i możliwe do zautomatyzowania, co pozwala na ich regularne wykonywanie i szybką reakcję na wykryte defekty. Umożliwia to również realizację ciągłego cyklu zwrotnego (feedback loop) między zespołem deweloperskim a zespołem testowym, co jest kluczowe dla iteracyjnego procesu poprawy jakości oprogramowania.

1.2.4 Testy Akceptacyjne (Acceptance Testing)

Definicja i Cel: Testy akceptacyjne są finalnym etapem procesu testowania oprogramowania, gdzie system jest oceniany z perspektywy użytkownika końcowego lub zgodności z biznesowymi wymaganiami. Celem testów akceptacyjnych jest potwierdzenie, czy system jest gotowy do wdrożenia i czy spełnia wszystkie ustalone kryteria akceptacji, które mogą być związane z funkcjonalnością, użytecznością, wydajnością i niezawodnością. Testy te są często przeprowadzane w środowisku produkcyjnym lub bardzo zbliżonym do produkcyjnego, aby zapewnić możliwie najbardziej autentyczne warunki użytkowania.

Scenariusze Testowe: Dla aplikacji mobilnej służącej do zamawiania jedzenia, scenariusze mogą obejmować:

  • Przypadek testowy 1:

    Proces zamówienia od wyboru restauracji do finalizacji płatności.

    • Wejście: Użytkownik przegląda menu, dodaje wybrane pozycje do koszyka i dokonuje płatności.

    • Oczekiwane wyjście: Zamówienie jest poprawnie złożone i płatność jest autoryzowana.

  • Przypadek testowy 2:

    Reakcja aplikacji na utratę połączenia z Internetem w trakcie składania zamówienia.

    • Wejście: Utrata połączenia z siecią w trakcie finalizacji zamówienia.

    • Oczekiwane wyjście: Aplikacja informuje użytkownika o błędzie i zapisuje zamówienie do późniejszego przesłania.

Narzędzia:

  • Cucumber lub SpecFlow: Narzędzia wspierające Behavior-Driven Development (BDD), pozwalające na definiowanie testów w języku naturalnym.

  • HP Quality Center: Zintegrowane środowisko do zarządzania testami, które wspomaga planowanie, śledzenie i raportowanie testów akceptacyjnych.

  • UserTesting lub BetaTesting: Platformy do przeprowadzania testów akceptacyjnych z rzeczywistymi użytkownikami, oferujące cenne wglądy w doświadczenia i opinie użytkowników.

Wyzwania i Najlepsze Praktyki:

  • Wyzwanie: Trudność w zdefiniowaniu wszystkich kryteriów akceptacji, które będą odzwierciedlać różnorodne oczekiwania i wymagania użytkowników.

  • Najlepsza praktyka: Ścisła współpraca z interesariuszami projektu oraz użytkownikami końcowymi w celu ustalenia kryteriów akceptacji oraz przeprowadzania iteracyjnych sesji testowych.

Przykłady Sukcesów i Niepowodzeń:

  • Sukces: Poprzez zastosowanie User Acceptance Testing (UAT), firma zdołała dopracować interfejs użytkownika aplikacji mobilnej, co znacząco zwiększyło jej przyjęcie na rynku.

  • Niepowodzenie: Brak odpowiednich testów akceptacyjnych dla systemu rezerwacji biletów lotniczych doprowadził do pominięcia krytycznych błędów w interfejsie użytkownika, co skutkowało złą prasą i koniecznością drogich poprawek po wdrożeniu.

Testy akceptacyjne są niezwykle ważne, ponieważ stanowią ostateczną weryfikację gotowości systemu do użytku. Ich zignorowanie może prowadzić do wprowadzenia na rynek produktu, który nie spełnia oczekiwań klientów, co może skutkować stratami finansowymi i reputacyjnymi. Współpraca z użytkownikami końcowymi i uwzględnienie ich opinii jest kluczowe dla sukcesu testów akceptacyjnych. Dobrze jest również włączyć do testów osoby niezwiązane z procesem tworzenia oprogramowania, ponieważ ich świeże spojrzenie może ujawnić problemy, które specjaliści mogli przeoczyć.

Metody:

  • Alpha/Beta Testing: Testy przeprowadzane przez wewnętrznych (Alpha) lub zewnętrznych (Beta) użytkowników.

  • Contract Acceptance Testing: Sprawdzenie zgodności systemu z warunkami umowy.

Przykłady:

  • Ocenianie przez rzeczywistych użytkowników wygody korzystania z nowej aplikacji mobilnej.

  • Walidacja spełnienia wymagań regulacyjnych przez system informatyczny szpitala.