Błędy składni, wykonania i logiki, przypadki testowe, debugger przeglądarki oraz ponowne sprawdzenie poprawki. Komentarze, dokumentacja techniczna i instrukcja użytkownika. Lekcja 10.4 kursu INF.03.
Testowanie to porównywanie rzeczywistego zachowania programu z wcześniej określonym wynikiem. Na egzaminie trzeba znaleźć błąd w kodzie, prześledzić stan zmiennych, poprawić działanie i przygotować dokumentację. W praktycznym projekcie test nie kończy się na otwarciu strony: obejmuje też formularz, obliczenia, dane błędne i sprawdzenie skutków poprawki.
Rodzaje błędów i czytanie komunikatów
Błąd składni oznacza zapis niezgodny z regułami języka, na przykład brak nawiasu lub dwukropka. Błąd wykonania pojawia się podczas pracy, gdy program próbuje wykonać niedozwoloną operację, na przykład podzielić przez zero. Błąd logiczny daje niewłaściwy wynik mimo poprawnej składni i możliwości uruchomienia. Zły próg rabatu może nie wywołać żadnego komunikatu błędu.
Komunikat czyta się razem z nazwą pliku, numerem wiersza i kontekstem. Miejsce wykrycia problemu nie zawsze jest miejscem jego powstania. Brak zamykającego nawiasu może zostać zauważony dopiero przy następnej instrukcji. Nie zaczynaj od kasowania wskazanego wiersza. Sprawdź również instrukcję poprzedzającą i to, jak program trafił do danego miejsca.
W Pythonie dzielenie liczby przez zero zgłasza ZeroDivisionError, czyli błąd dzielenia przez zero. Brak definicji użytej nazwy może zgłosić NameError. Taki komunikat zawęża poszukiwania, lecz nie podejmuje decyzji, jaki wynik aplikacja powinna zwrócić dla braku danych. Wymaganie określa autor zadania, a dokumentacja języka wyjaśnia mechanizm błędu. Rozróżnienia opisuje dokumentacja Pythona. Przypadek testowy i wartości graniczne
Przypadek testowy opisuje dane, czynności i oczekiwany wynik. Dla funkcji przyznającej rabat trzeba ustalić próg. Załóżmy, że od trzech sztuk obowiązuje cena 20 zł, a poniżej trzech cena 25 zł. Test dwóch sztuk powinien dać 50 zł, trzech 60 zł, a czterech 80 zł. Testowanie wyłącznie pięciu sztuk nie sprawdza, czy rabat zaczyna się w prawidłowym miejscu.
Wartości graniczne leżą na granicy warunku i tuż obok niej. Dla minimum równego jeden sprawdza się zero, jeden i dwa. Dla listy sprawdza się brak elementów, jeden element i wiele elementów. Przy formularzu sprawdza się także pusty tekst, nieprawidłowy zapis i wielokrotne uruchomienie operacji. Oczekiwane zachowanie dla danych błędnych musi być ustalone przed oceną wyniku.
Test jednostkowy sprawdza wydzielony fragment, na przykład funkcję liczącą kwotę. Test integracyjny bada współpracę części, na przykład skryptu i bazy. Test całego procesu przechodzi przez działania użytkownika, od otwarcia formularza do potwierdzenia. Te poziomy wykrywają różne problemy. Poprawna funkcja nie gwarantuje, że przycisk przekazuje do niej odpowiednie dane.
Przykładowy zapis testu powinien pozwolić innej osobie go powtórzyć. „Formularz nie działa” jest za mało dokładne. „Po wpisaniu 3 w pole liczby sztuk i kliknięciu Oblicz widoczna kwota to 75 zł, oczekiwano 60 zł” wskazuje dane, działanie i różnicę. Do raportu dopisz wersję aplikacji lub nazwę sprawdzanego pliku, aby wiadomo było, czego dotyczył wynik.
Od objawu do przyczyny
Debugowanie to ustalanie przyczyny błędu na podstawie obserwacji programu. Najpierw odtwórz problem na możliwie małym przykładzie. Potem porównaj dane wejściowe, stan pośredni i wynik. Zmieniaj jedną uzasadnioną rzecz naraz, aby wiedzieć, co spowodowało różnicę. Przypadkowe poprawki w kilku plikach utrudniają potwierdzenie przyczyny.
Poniższy program ma poprawną składnię, ale nie zgadza się z progiem rabatu przyjętym w poprzedniej sekcji:
function obliczKwote(ilosc) {
let cena = 25;
if (ilosc > 3) {
cena = 20;
}
return cena * ilosc;
}
console.log(obliczKwote(3));
Wynik to 75. Warunek wymaga więcej niż trzech sztuk, więc dla trzech cena zostaje równa 25. Przyczyna leży w operatorze porównania. Zastąpienie go operatorem „większe lub równe” naprawia tę granicę:
if (ilosc >= 3) {
cena = 20;
}
To fragment zastępujący warunek wewnątrz poprzedniej funkcji, a nie osobny kompletny program. Po zmianie wywołanie dla trzech sztuk zwraca 60. Nie należy zmieniać ceny bazowej na 20, bo wtedy dwa zamówione produkty także dostałyby rabat. Poprawka ma przywrócić regułę, a nie tylko dopasować jeden wynik.
Debugger w przeglądarce
Debugger przeglądarki pozwala zatrzymać wykonanie JavaScript i obejrzeć stan. Otwórz stronę z pełną funkcją z poprzedniego przykładu w pliku JS, uruchom narzędzia deweloperskie i przejdź do panelu Sources (źródła). Otwórz plik i ustaw punkt przerwania, czyli miejsce zatrzymania, na wierszu z warunkiem. Odśwież stronę, aby wykonać skrypt ponownie.
Po zatrzymaniu sprawdź wartości ilosc i cena w panelu zakresu zmiennych albo przez dodanie ich do obserwowanych wyrażeń. Powinny wynosić 3 i 25. Przejdź jeden krok dalej i sprawdź, czy wykonanie weszło do wnętrza warunku. W błędnej wersji nie wejdzie. Ta obserwacja potwierdza, że problem jest związany z decyzją, a nie z działaniem mnożenia.
Step over (krok bez wchodzenia) wykonuje bieżącą instrukcję, traktując wywołanie funkcji jako całość. Step into (krok do wnętrza) pozwala wejść do wywoływanej funkcji, a Step out (wyjście z funkcji) wraca do miejsca jej wywołania. Resume (wznów) kontynuuje do następnego zatrzymania. Nazwy i ikony mogą zależeć od przeglądarki; znaczenie operacji pozostaje podobne. Procedurę opisuje dokumentacja Chrome DevTools. Stos wywołań pokazuje, które funkcje doprowadziły do aktualnego miejsca. Jest przydatny, gdy ten sam kod uruchamia kilka przycisków. Debugger strony nie zatrzyma automatycznie kodu PHP wykonywanego na serwerze. Dla PHP używa się narzędzi i logów po stronie serwera. Konsola JavaScript może zobaczyć odpowiedź PHP, lecz nie odczytuje bezpośrednio jego zmiennych.
Poprawka i test regresji
Test regresji to sprawdzenie, czy późniejsza zmiana nie przywróciła wcześniej usuniętego problemu. Po naprawie progu zapisz test trzech sztuk jako przypadek kontrolny. Następnie sprawdź także dwie i cztery sztuki, ponieważ poprawka warunku wpływa na podział całego zakresu. Jeżeli program ma obsługiwać brak towaru lub niepoprawną liczbę, te wymagania potrzebują osobnych przypadków.
Walidacja składni sprawdza zgodność zapisu z regułami języka. Polecenie PHP z opcją -l może sprawdzić składnię pliku bez normalnego wykonania programu, ale nie potwierdzi wyniku obliczeń i poprawności połączenia z bazą. Podobnie walidator HTML nie ocenia pełnej logiki aplikacji. Zakres narzędzia trzeba zestawić z rodzajem problemu.
Raport po poprawce powinien pokazać: jaki błąd odtworzono, jaka była przyczyna, co zmieniono i jakie przypadki sprawdzono ponownie. Nie trzeba przepisywać całego kodu. Zapis oczekiwanego i rzeczywistego wyniku daje mocniejszy dowód niż ogólne stwierdzenie o poprawnym działaniu.
Komentarze i dokumentacja
Komentarz wyjaśnia kod osobie, która będzie go czytać. Najbardziej pomaga przy założeniach i powodach nietypowej decyzji. Opis „zwiększ licznik o jeden” przy oczywistym zwiększeniu zwykle nic nie wnosi. Opis „próg obejmuje także dokładnie trzy sztuki” dokumentuje regułę, którą łatwo omyłkowo zmienić. Nieaktualny komentarz trzeba poprawić razem z kodem.
W JavaScript komentarz jednoliniowy zaczyna się od // i trwa do końca wiersza. Komentarz blokowy zapisujesz między /* i */; może obejmować kilka wierszy. Interpreter pomija komentarze, ale pozostają one w źródle dla czytającej je osoby. Przy poprawionym warunku zapisz powód wyboru granicy:
// Rabat obejmuje także dokładnie trzy sztuki, zgodnie z cennikiem.
if (ilosc >= 3) {
cena = 20;
}
To komentarz o regule biznesowej. Po zmianie cennika sprawdź zarówno warunek, jak i jego opis, aby nie przekazywały sprzecznych informacji.
Dokumentacja techniczna opisuje przeznaczenie programu, strukturę plików, wymagane wersje i sposób uruchomienia. Powinna wskazać konfigurację bazy, przygotowanie danych i sposób sprawdzenia działania. Hasło do rzeczywistego konta nie powinno być publicznym elementem instrukcji. Warto rozdzielić przykładową konfigurację od sekretów używanych na danym stanowisku.
Instrukcja użytkownika opisuje czynności z punktu widzenia osoby korzystającej z aplikacji. Dla kalkulatora wyjaśnia otwarcie strony, dozwolone wartości, przycisk obliczenia i odczyt wyniku. Powinna także powiedzieć, co zrobić po komunikacie o błędzie. Nazwy zmiennych, zapytania SQL i lokalizacja punktu przerwania zwykle nie pomagają temu odbiorcy. Ten sam program potrzebuje więc różnych dokumentów dla różnych zadań.
Na egzaminie
Przy szukaniu błędu najpierw oblicz oczekiwany wynik i prześledź konkretne wartości. Odróżnij brak średnika od złego progu i od błędu połączenia. Jeśli wymagany jest debugger, pokaż punkt zatrzymania i stan zmiennych, a nie wyłącznie otwartą konsolę. Dokumentacja powinna dotyczyć oddanej wersji programu.
Pułapka: poprawka, która daje dobry wynik tylko dla jednego sprawdzonego wejścia, może psuć pozostałe przypadki. Po zmianie sprawdź obie strony granicy warunku.
W pracy praktycznej zachowaj wymagane zrzuty i pliki, usuń przypadkowe komunikaty diagnostyczne z końcowego widoku oraz ponownie przejdź główny scenariusz. Użytkownik powinien otrzymać zrozumiały rezultat, a osoba sprawdzająca możliwość odtworzenia wyniku.
Ściąga
Pojęcie
Co sprawdza lub opisuje
błąd składni
niepoprawny zapis języka
błąd wykonania
niedozwolona operacja podczas pracy
błąd logiczny
wynik sprzeczny z wymaganiem
przypadek testowy
wejście, czynności, oczekiwany wynik
breakpoint
punkt zatrzymania debuggera
test regresji
brak powrotu wcześniejszego błędu
dokumentacja techniczna
budowa, wymagania, uruchomienie
instrukcja użytkownika
obsługa i reakcja na komunikaty
Pobierz ściągę PDF