Przejście otoczone stosem książek

Co musisz wiedzieć, żeby zacząć testowanie komponentów React?

Wprowadzenie testów to najlepszy sposób na podniesienie jakości i niezawodności tworzonego przez Ciebie oprogramowania. Jak pokazała przeprowadzona przeze mnie ankieta, czytelnicy bloga świetnie zdają sobie sprawę. Mimo najlepszych chęci, pierwsze kroki w świecie testowania mogą być przytłaczające. Terminologia, konfiguracja środowiska, o samym pisaniu testów nie mówiąc. Tym razem udowadniam, że to żadne rocket science. Po przeczytaniu tego wpisu będziesz mógł zabrać się za testowanie komponentów React.

Czego dowiesz się z lektury tego artykułu?

  • Czym są asercje?
  • Co różni testy jednostkowe, integracyjne i end-to-end?
  • Piramida testowania czyli skuteczny rozkład zasobów
  • Jak utrwalić sobie tyle teorii?
  • Jakie narzędzia wykorzystuje się do testowania komponentów?
  • Jak skonfigurować te narzędzia w aplikacjach utworzonych za pomocą create-react-app?
  • Co padnie ofiarą moich pierwszych testów?

Testerski żargon

Z myślą o osobach, które dopiero zaczynają swoją przygodę z testowaniem, przygotowałem krótkie objaśnienie kluczowych pojęć.

Asercja (ang. assertion)

To założenie logiczne, które stanowi sedno każdego testu. Takie założenie sprawdza, czy kod działa w oczekiwany przez nas sposób. Aby nie utonąć w abstrakcji, zobaczmy, jak wygląda przykładowa asercja:

Recepta na sukces w każdym rodzaju testów to właśnie odpowiednia ilość poprawnie skonstruowanych asercji. Cała sztuka testowania polega na podjęciu decyzji, co należy zweryfikować, a co pominąć. Jak to w programistycznym rzemiośle bywa, najlepszym sposobem na wyrobienie sobie takiej intuicji jest praktyka, którą zajmiemy się w kolejnych wpisach.

Testy jednostkowe (ang. unit tests)

Polegają na weryfikowaniu działania najmniejszych części składowych aplikacji. Operujemy bezpośrednio na kodzie źródłowym, mamy pełny wgląd w całą mechanikę jednostki. Izolujemy tę część składową od reszty systemu, koncentrujemy się wyłącznie na niej, bez uwzględnienia współpracy z resztą systemu. Wszystkie zewnętrzne usługi, takie jak pobieranie danych z bazy, zastępuje się mockami czyli atrapami, które imitują ich działanie.

Czym tak naprawdę jest ta cała „najmniejsza część składowa”? TO ZALEŻY (czyli ulubiona odpowiedź każdego początkującego ;)). W vanilla JS są to funkcje/obiekty/klasy, w React to oczywiście komponenty. Z uwagi na propsy, event handlery, wyświetlanie warunkowe i inne kluczowe zagadnienia z Reacta, o których możesz poczytać tutaj, nie będziemy narzekali na brak pracy przy testach jednostkowych.

Testy integracyjne (ang. integration tests)

Sprawdzają współpracę pomiędzy jednostkami, które składają się na określoną usługę/moduł aplikacji. Dobrym przykładem testu integracyjnego byłoby wprowadzenie frazy w komponencie Searchbar i sprawdzenie, czy komponent CoinList zwrócił listę wyników.

Testy end-to-end

Skupiają się na sprawdzaniu działania aplikacji/modułu z perspektywy użytkownika. Traktujemy aplikację jako czarną skrzynkę i odtwarzamy scenariusz jej wykorzystania w docelowym środowisku (w przypadku Reacta będzie to przeglądarka).

Na przykładzie trackera kryptowalut: użytkownik uruchamia aplikację (asercja sprawdzająca czy interfejs się załadował), czeka kilka sekund na załadowanie listy kryptowalut (asercja weryfikująca zawartość listy), wyszukuje kryptowalutę w oparciu o jej pełną nazwę lub akronim (asercja sprawdzająca zawartość wyszukiwarki i listy), po czym wraca do pełnej listy (asercja sprawdzająca zawartość listy).

Piramida testowania

Będziemy pisali testy zgodnie z piramidą testowania:

Piramida testowania

Wielkość każdego z poziomów piramidy odzwierciedla ilość testów danego rodzaju.

Jak widać, skupimy się przede wszystkim na testach jednostkowych. Pewność, że każdy komponent w izolacji spełnia postawione mu zadania, to solidny fundament.

Jednak niezawodny interfejs to coś więcej niż suma składających się na nie wyizolowanych komponentów. To poprawna współpraca pomiędzy nimi jest najważniejsza dla działania aplikacji. Stąd testy integracyjne, chociaż będzie ich trochę mniej, są dla nas równie istotne jak testy jednostkowe.

Dlaczego testy end-to-end są na samym szczycie? Przecież są świetne w wykrywaniu bugów, na które użytkownik może natknąć się podczas swojej codziennej pracy z systemem. Niestety, mają dwie zasadnicze wady. Po pierwsze, są bardzo kruche. Małe zmiany w interfejsie i cały test się sypie, co wiąże się z wysokimi kosztami utrzymania. Ponadto, w porównaniu z testami jednostkowymi są piekielnie wolne.

Jak utrwalić sobie tyle teorii?

Aby swobodnie zajmować się testowaniem, warto sobie utrwalić tę terminologię. Natkniesz się na nią dosłownie wszędzie, w każdej rozmowie, artykule, książce związanej z tą tematyką.

Najskuteczniejszym sposobem – jaki poznałem do tej pory – na szybkie utrwalanie teorii jest metoda Anki. Aby dowiedzieć się, jak korzystać z tego świetnego narzędzia, zerknij do wpisu Anki, czyli jak zapamiętuję WSZYSTKO czego się uczę.

Narzędzia do testowania

Na pełne środowisko testowe aplikacji React składa się: struktura testów, matchery asercji, wyświetlanie wyników, mocki, raporty pokrycia, środowisko imitujące przeglądarkę.

Aby zapewnić tak dużą liczbę funkcjonalności, często korzysta się z kombinacji kilku narzędzi. Aby ograniczyć konfiguracyjne szaleństwo, ograniczyłem tę liczbę do niezbędnego minimum. Jest szansa, że dzięki temu skupimy się na pisaniu testów zamiast oddawać się wątpliwej przyjemności prowadzenia walki ze środowiskiem ;).

Jest

Głównym filarem całego środowiska będzie Jest, framework z stajni Facebooka. W aplikacjach utworzonych za pomocą create-react-app jest on zapakowany, skonfigurowany i gotowy do działania. Czego chcieć więcej.

Jest zapewnia wszystkie z kluczowych funkcjonalności, na które składa się środowisko testowe. Dzięki temu możemy od razu zabierać się za pisanie testów jednostkowych i integracyjnych.

Więcej na temat Jest dowiesz się z przystępnie napisanej dokumentacji. Warto zajrzeć.

Alternatywy dla Jest: Mocha + Chai (popularny wariant w ekosystemie Reacta) oraz Jasmine (na której Jest był wzorowany).

Enzyme

Enzyme to biblioteka przygotowana przez Airbnb specjalnie z myślą o testowaniu komponentów React. Ułatwia renderowanie, przeszukiwanie i tworzenie asercji na komponentach.

Enzyme renderuje komponent i zapewnia nam intuicyjne API, które pozwala sprawdzić, co udało się wyrenderować. Jeżeli zerkniemy „pod maskę” Enzyme, natkniemy się na cheeriojs, małą bibliotekę implementującą funkcjonalności jQuery Core. Stąd przeszukiwanie komponentów z Enzyme do złudzenia przypomina przeszukiwanie DOM z jQuery, z czym na pewno miałeś już styczność.

Enzyme daje nam trzy możliwości renderowania:

  • shallow -renderujemy wyłącznie wskazany komponent, bez dzieci
  • full -renderujemy komponent i wszystkie jego dzieci
  • static – renderujemy statyczny kod HTML

Shallow i static rendering nie wymagają korzystania z DOM, dzięki czemu testy tego typu wykonują się naprawdę szybko. Za to full rendering wymaga dostarczenia pełnego DOM API, za które posłuży nam jsdom zapakowane razem z Jest.

Nasze testy jednostkowe będą korzystały przede wszystkim z shallow renderingu, podczas gdy full rendering przyda się przy testach integracyjnych.

Aby dodać Enzyme do środowiska testowego, musimy zainstalować dwa pakiety: enzyme oraz enzyme-adapter-react-16. Enzyme korzysta z adapterów do zapewnienia kompatybilności z wersją Reacta używaną w projekcie.

Aby aktywować Adapter, musimy podpiąć go do Enzyme w pierwszym pliku konfiguracyjnym 🙁 (i jedynym! :)) naszego środowiska testowego. W aplikacjach utworzonych za pomocą create-react-ap, Jest spodziewa się, że powstanie on pod ścieżką /src/setupTests.js.

Na dodatek w każdym z testów chcemy mieć swobodny dostęp do trzech wariantów renderowania Enzyme. Zaoszczędzimy sobie importowania i podepniemy je do obiektu globalnego.

Tyle w temacie konfiguracji, jesteśmy gotowi!

Więcej o enzyme dowiesz się z dokumentacji.

Alternatywą dla Enzyme jest react-testing-library autorstwa Kenta C. Doddsa.

Aktualizacja z przyszłości: Swoje przygody z Jest i Enzyme opisałem w kolejnych wpisach z tej serii: „Jak pisać testy jednostkowe komponentów React z Jest i Enzyme” oraz „Jak pisać testy integracyjne komponentów React z Jest i Enzyme”.

Cypress.io

Listę narzędzi zamyka Cypress.io, framework do testów end-to-end. Ostatnimi czasy coraz więcej o nim słychać, praktycznie w samych superlatywach, więc rzucimy okiem na to, jak sprawdza się w praktyce.

I bez niespodzianek, więcej na temat cypress.io możesz przeczytać w dokumentacji ;).

Aktualizacja z przyszłości: o tym czy Cypress zasługuje na swoją reputację przeczytasz w artykule: „Jak pisać testy end-to-end aplikacji React z frameworkiem Cypress”.

Co będziemy testowali?

Tak się składa, że mamy do dyspozycji małą aplikację, która świetnie nadaje się do poddania testom. Jest nią crypto-tracker, który zbudowałem w ramach serii „Pierwszy projekt w ReactJS”. W trzech kolejnych wpisach zaprezentuję na jej przykładzie testy jednostkowe, integracyjne oraz end-to-end.

Podsumowanie

Liczę, że po przeczytaniu tego wpisu jesteś gotowy na testową jazdę bez trzymanki ;).

Podobał Ci się dzisiejszy artykuł? Udostępnij go w Twoich ulubionych mediach społecznościowych. Może znajdzie się ktoś, dla kogo również będzie wartościowy.

Bądź na bieżąco. Wystarczy polubić fanpage AlgoSmart na fejsie, obserwować mój profil na Twitterze i regularnie odwiedzać portal Polski Front-end.

Jeżeli jeszcze nie słyszałeś o serwerze polskiego front-endu na Discordzie, to zachęcam do udziału. Ledwo co dołączyłem, ale jestem naprawdę pozytywnie zaskoczony tym miejscem. Można porozmawiać z aktywną społecznością na dowolny temat związany z JavaScript. Ciekawa alternatywa dla osób, które tak jak ja, nie są fanami dyskusji na fejsbukowych grupach :). Zainteresowanych odsyłam tutaj.

Do zobaczenia w kolejnym wpisie. Będzie powstawał w przerwach od zmagań z sesją egzaminacyjną, co utrudnia oszacowanie, kiedy dokładnie zostanie opublikowany. Na pewno jeszcze w czerwcu :)!

Zdjęcie tytułowe autorstwa: unsplash-logoGlen Noble

Marcin Czarkowski

Cześć! Ja nazywam się Marcin Czarkowski, a to jest AlgoSmart - blog, na którym dzielę się wiedzą o ReactJS, JavaScript oraz CSS. Od niedawna tworzę materiały na YouTube, warto rzucić okiem :).

  • Powroźnik Kamil

    Polecam tego allegrowicza. Rzeczowy artykuł, który jasno przedstawia sprawę testów. Bardzo dobrze, że w prosty sposób są wytłumaczone poszczególne terminy typu unit testing czy e2e.