Nowoczesne testowanie kodu w JavaScript. Część Trzecia – Pokrycie kodu testami.

Tym razem napiszę o trochę innym aspekcie testowania, o sprawdzaniu jak wygląda pokrycie testami tworzonego przez programiste kodu. Polega to mniej więcej na obliczaniu przy pomocy odpowiedniego narzędzia, ile razy każda linijka testowanego kodu została wywołana podczas przeprowadzania testów.

Cel mierzenia tego typu danych, może nie być od razu oczywisty, ale uwierzcie mi, jest to bardzo przydatne, szczególnie jeżeli nasza aplikacja coraz bardziej się rozrasta. Dzięki testom pokrycia możemy wykryć nie tylko te fragmenty kodu, które nie zostały przetestowane, ale też na przykład te, które są niepotrzebnie testowane kilka razy.

Pokrycie kodu w JavaScript Es6

Narzędzie, które wykorzystam do przeprowadzania testów pokrycia to bardzo popularny istanbul. Dodanie go do projektu jak i korzystanie z niego jest naprawdę proste.

Aby zainstalować istanbul, jak zapewne się domyślacie, trzeba skorzystać z npma. Ponieważ jednak chcę mierzyć pokrycie kodu w projekcie, w którym używam składni ES6, muszę zainstalować konkretną wersję tego istanbula (oczywiście pracuję cały czas na projekcie z poprzednich postów. Jego aktualny stan, przed dodaniem testów pokrycia, opisany jest tutaj).

Z głównego katalogu projektowego, w terminalu wpisuję następujące polecenie:

Tak jak wspomniałem wyżej, musi to być ta konkretna wersja. Aktualnie istanbul jest w wersji 0.4, ale nie obsługuje ona ES6, więc będę korzystać z alfy wersji 1.x.

Po zainstalowaniu istanbula, trzeba zmienić zawartość npmowego skryptu test, tak aby korzystał z nowego narzędzia. W obiekcie skripts w pliku package.json, zmieniam pole test:

Nie będę dokładnie tłumaczył tego skryptu, bo szczerze mówiąc sam tylko powierzchownie orientuje się do czego służą poszczególne komendy 🙂 . Chodzi o to, że uruchamiam istanbul (pierwszy element skryptu) tak aby zmierzył (drugi element skryptu) pokrycie testów mocha (reszta skryptu). Jak widać do mocha odnoszę się tu pełną ścieżką do node_modules oraz nie korzystam ze standardowej komendy uruchamiającej testy a takiej z podkreślnikiem. Tu znów muszę przyznać się do ignorancji 🙂 , nie wiem dlaczego musi to być akurat ta wersja, ale tylko ona działa z istanbulem.

Po uruchomieniu tego skryptu w konsoli, powinien ukazać się mniej więcej coś takiego:

Oprócz standardowych wyników przeprowadzonych testów pojawiła się także tabelka zawierająca informacje o pokryciu kody testami. Jak widać oprócz informacji o tym przez ile linijek kodu przeszedł test są też dane na temat tego ile funkcji zostało przetestowanych, ile wyrażeń oraz czy sprawdzone zostały wszystkie drogi w wyrażeniach warunkowych.

W tym miejscu muszę odbić od tego przykładu i wyjaśnić kilka spraw. Pokrycie 100% to pożądana sytuacja lecz nie zawsze będzie możliwa lub konieczna. Ze względu na ograniczenia np. czasowe zdarza się pomijać testowanie każdego elementu kodu. Nie jest to sytuacja idealna ale tak wygląda życie 🙂 Inna sprawa to to, że 100% pokrycie kodu testami nie oznacza, że wszystko jest dobrze. Niska liczba pokrycia to sygnał, że coś jest nie tak, ale wysoka wcale nie potwierdza, że kod jest przetestowany poprawnie.

Wracając do przykładu, oprócz danych, które widzimy w konsoli, istanbul generuje bardzo obszerne raporty. Podczas testów w projekcie tworzony jest katalog coverage, jeżeli otworzymy znajdujący się wewnątrz plik html, można zobaczyć w ilu procentach pokryte testami zostały poszczególne pliki projektu. W tym momencie w projekcie mam tylko jeden plik – index.js. Mogę klikną jego nazwę aby zobaczyć dokładniejsze dane:

Tutaj można zobaczyć testowany plik, oraz wiele ciekawych danych na temat przeprowadzonych testów. Pierwszą rzeczą, która rzuca się w oczy to informacja o tym, które linijki kodu były przez testy uruchamiane i ile razy. Tym razem pokrycie testów jest stu procentowe, ale gdybym usunął wszystkie napisane wcześniej testy i zostawił tylko ostatni, wynik wyglądał by tak:

Na czerwono oznaczone zostały linijki kodu, które nie zostały w ogóle uruchomione. Jest to sygnał dla programisty, że warto zwrócić uwagę na to jak działają testy i czy na pewno ich aktualny stan jest zadowalający.

Wracając do pierwszego raportu, mogę zauważyć jeszcze jedną rzecz. Niektóre linijki kodu uruchamiane są dość często. Czasem nic to nie znaczy. Na przykład przejście przez pierwszy warunek funkcji check odbędzie się za każdym razem, niezależnie od tego co sprawdza test. Jednak widać też, że konstruktor klasy PrimeChecker uruchamiany jest sześć razy. Dzieje się tak dlatego, że tworzę nową instancję klasy w metodzie BeforeEach w testach. Oznacza to, że instancja klasy tworzona jest przed każdym testem. W tym wypadku nie jest to koniecznie, lepiej byłoby stworzyć jedną instancję przed wszystkimi testami.

Mogę z łatwością osiągnąć powyższe, zmieniając w pliku test.spec.js, metodę BeforeEach na Before. Ta druga uruchamiana jest tylko raz, przed wszystkimi testami, czyli dokładnie to o co mi chodzi. Tak wygląda test.spec.js, po zmianie:

A taki raport zostanie wygenerowany przez istanbul po uruchomieniu testów:

Tym razem konstruktor został wywołany tylko raz. Sukces! W tym przykładzie może wydawać się to bez znaczenia, ale gdy w prawdziwym projekcie testów jest dosłownie tysiące, takie usprawnienie, może naprawdę pomóc. Generalnie chodzi o to, że mierzenie pokrycia kodu testami pozwala na znalezienie i szybkie rozwiązanie takich problemów z testami, które normalnie byłyby dla programisty od razu widoczne.

Na dziś to tyle, w następnej części serii pokażę jak w testach radzić sobie z asynchronicznością 🙂 . Jeżeli chcesz być na bieżąco z postami na blogu zachęcam do polubienia mojej strony na facebooku. Zawsze zamieszczam tam informacje o wszystkich nowościach. Jest to też dobre miejsce na kontakt ze mną. Na wszystkie pytania zawsze odpowiem 🙂 .

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *