Dobre dane testowe, czyli jakie?
Żeby testy miały sens, musimy zrobić je dobrze. W tym celu będą nam potrzebne sensowne dane testowe.
Wymyślenie i spisanie pierwszych 10 wartości, które przyszły Ci do głowy, brzmi kusząco, ale czy to najlepsze wyjście? To kwestia dyskusyjna 😉
Jak w takim razie wybrać dane do testów?
Wyobraź sobie, że testujesz jakąś fajną gierkę.
Zanim rozpoczniesz rozgrywkę, musisz się zarejestrować. I tutaj przechodzimy do kluczowego punktu: do wymagań. Właśnie na ich podstawie będziemy w stanie stworzyć porządne dane testowe.
Możemy to zrobić na kilka różnych sposobów. Pomogą nam w tym metody zarówno białoskrzynkowe jak i czarnoskrzynkowe.
Żeby zastosować metodę białoskrzynkową, musimy znać kod aplikacji i bazować na nim. W przypadku metod czarnoskrzynkowych znajomość kodu NIE jest konieczna i właśnie od tych metod zaczniemy.
Metody czarnoskrzynkowe
W tej sytuacji traktujemy aplikację jak czarną skrzynkę – nie wiemy co jest w środku i na tym etapie nie potrzebujemy tej wiedzy. Sprawdzamy, co robi aplikacja i jak reaguje na dane testowe.
Załóżmy, że według wymagań, nazwa użytkownika powinna zawierać od 5 do 10 znaków. W tej sytuacji całkiem dobrym wyborem będzie analiza wartości brzegowych.
Analiza wartości brzegowych
Ta technika koncentruje się na testowaniu granicznych wartości danych wejściowych. Zakłada, że błędy w aplikacji występują wokół granic dopuszczalnych wartości.
W tym przypadku dopuszczalne wartości to wszystkie liczby między 5 a 10 znaków. Rozrysujmy to sobie:
Żeby poprawnie zastosować tę technikę, musimy teraz wybrać skrajne wartości (czyli 5 i 10) oraz liczby o 1 mniejsze, oraz o 1 większe.
Łącznie powinniśmy otrzymać 6 przypadków testowych:
- Nazwa użytkownika składająca się z 4 znaków (dana niepoprawna);
- Nazwa użytkownika składająca się z 5 znaków (dana poprawna);
- Nazwa użytkownika składająca się z 6 znaków (dana poprawna);
- Nazwa użytkownika składająca się z 9 znaków (dana poprawna);
- Nazwa użytkownika składająca się z 10 znaków (dana poprawna);
- Nazwa użytkownika składająca się z 11 znaków (dana niepoprawna);
To, co widzisz wyżej nazywamy metodą trójpunktową. Jest jeszcze odmiana dwupunktowa, gdzie wybieramy wartości o 1 mniejsze od wartości minimalnej, oraz o 1 większe od wartości maksymalnej.
Łącznie powinniśmy otrzymać 4 przypadki testowe:
- Nazwa użytkownika składająca się z 4 znaków (dana niepoprawna);
- Nazwa użytkownika składająca się z 5 znaków (dana poprawna);
- Nazwa użytkownika składająca się z 10 znaków (dana poprawna);
- Nazwa użytkownika składająca się z 11 znaków (dana niepoprawna);
Analiza wartości brzegowych to prosty sposób na przetestowanie najbardziej krytycznych danych. Możemy ją zastosować w dowolnym momencie… jeśli znamy już wymagania. 😉
Klasy równoważności
Jest to technika, o którą byłem wielokrotnie pytany na rozmowach kwalifikacyjnych, więc zdecydowanie warto się jej przyjrzeć 😎
Przypomina ona nieco analizę wartości brzegowych, ale zamiast skrajnych wartości, wyznaczamy tu klasy.
Zakładamy tu, że jeśli testujemy jedną wartość z danej klasy, to wynik testu będzie taki sam dla wszystkich innych wartości w tej samej klasie.
Wszystko fajnie, tylko jak poprawnie wyznaczyć klasy?
Rozpiszmy to znowu dla nazwy użytkownika. Zaznaczmy na wykresie, gdzie znajdują się poprawne dane, a gdzie niepoprawne:
Pięknie nam to pokazuje, ile potrzebujemy klas równoważności. Sztuka lepsza niż ta od Leonardo da Vinci 😅
Gołym okiem widać, że potrzebne są nam 3 klasy:
- Z wartościami od 0 do 4 (niepoprawne wartości);
- Z wartościami od 5 do 10 (poprawne wartości);
- Z wartościami od 11 do nieskończoności (niepoprawne wartości).
W testach możesz wylosować po jednej danej z każdego przedziału, czyli na przykład 3, 8 i 38. W rezultacie mamy tu mniej przypadków testowych niż w poprzedniej technice.
Tablica decyzyjna
Skomplikujmy sobie nieco sprawę i do nazwy użytkownika dodajmy hasło. Mamy teraz dużo więcej przypadków do przetestowania, ale spokojnie, z pomocą przybywa tablica decyzyjna.
Polega na tym, że w formie tabelki rozpisujemy sobie jakie przypadki mamy do sprawdzenia i w ten sposób zapisujemy każdą możliwą kombinację.
Dla nazwy użytkownika i hasła tablica decyzyjna będzie wyglądać tak:
Dzięki tablicy decyzyjnej możemy w prosty sposób stworzyć minimalny zestaw testów, który zapewnia pokrycie wszystkich istotnych kombinacji danych.
Ta technika sprawdzi się również przy większej ilości pól. Jeśli masz ochotę, to w ramach praktyki spróbuj sobie rozpisać podobną tablicę dla nazwy użytkownika + adresu e-mail + hasła.
W końcu praktyka czyni mistrza. 😁
Metody białoskrzynkowe
Przejdźmy do metod, gdzie działamy z kodem aplikacji. Testy białoskrzynkowe przydają się w szczególności programistom (w końcu też testują swój kod), ale jeśli sami mamy dostęp do kodu, to nikt nam nie broni, żeby z tego skorzystać.
Skupmy się na pokryciu instrukcji oraz pokryciu decyzji.
Pokrycie instrukcji
Pokrycie instrukcji pozwala zrozumieć, jak dobrze zestaw testów sprawdza cały kod programu. Korzystając z tej techniki musimy zadbać, aby wybrane dane testowe przeszły po jak największej liczbie linii kodu.
Załóżmy, że testujesz program z 100 liniami kodu, a Twoje testy sprawdzają tylko 70 z nich. W takiej sytuacji pokrycie instrukcji wynosi 70%. Im wyższe to pokrycie, tym mniejsza szansa, że przepuścimy na produkcję jakiegoś buga.
Pokrycie decyzji
Pokrycie decyzji testuje się podobnie jak pokrycie instrukcji, z tą różnicą, że zamiast sprawdzać pokrycie linii kodu, sprawdzamy tu, czy przetestowaliśmy każdą możliwą decyzję.
Przykład: jeśli w kodzie znajduje się instrukcja warunkowa if, pokrycie decyzji oznacza, że testy zostały przeprowadzone tak, aby zarówno warunek prawdziwy (true), jak i fałszywy (false), zostały przetestowane.
Ta technika pozwala nam sprawdzić, czy program reaguje poprawnie zarówno w przypadku spełnienia, jak i niespełnienia warunków.
Żeby obliczyć poziom pokrycia decyzji, musimy podzielić liczbę decyzji pokrytych testami przez liczbę wszystkich decyzji. Czyli, jeśli w kodzie możemy podjąć łącznie 100 decyzji, a testy pokrywają 45 decyzji, to pokrycie wynosi 45%.
Ciekawostka: 100% pokrycia decyzji gwarantuje 100% pokrycia instrukcji, ale nie działa to odwrotnie.
A czy można inaczej?
Jasne, że można! Czasami nawet nie mamy wyboru…
Może się zdarzyć, że będziemy mieć bardzo mało czasu na testy. Dodajmy do tego braki w dokumentacji i skoki ciśnienia, gdy w nią zaglądamy.
W takich sytuacjach możemy nie mieć czasu na rozpisywanie tablic decyzyjnych i analizę wartości brzegowych do każdej części aplikacji, która powinna być gotowa na wczoraj. Wtedy najlepiej bazować na naszym doświadczeniu i wykonać testy eksploracyjne.
Jeśli dobrze znamy testowaną aplikację, to na podstawie naszego doświadczenia możemy wywnioskować, gdzie najczęściej pojawiają się awarie i jakie dane mogą je wywoływać.
Warto sprawdzić, czy nie będzie to spacja. 😈