Dzisiejszy wpis będzie dotyczył testowania aplikacji w React. Będzie to totalny wstęp i artykuł kieruję głównie do osób, które nie miały w ogóle styczności z testowaniem w React.
Temat ten jest na tyle złożony, że na pewno pojawi się kilka artykułów dotyczących testowania, więc zapraszam do śledzenia bloga.
Motywacją do napisania tego artykułu był fakt, że często w aplikacjach testy po prostu nie występują. Testowanie schodzi na drugi plan ze względu na terminy, wymagania, zmiany w kodzie, brak zasobów itd. Z drugiej strony testy potrafią pomóc i ułatwić znalezienie błędów, które czasami mogłoby pozostać niezauważone przez dłuższy czas…
Pierwszy artykuł będzie wstępem do tego, aby w ogóle zacząć pisać podstawowe testy i z czasem dodawać nowe rodzaje testów do naszej aplikacji. Ma to być pewnego rodzaju inspiracja do tego, że może jednak warto zacząć to robić. Niektóre testy możemy napisać stosunkowo szybko i warto w to zainwestować. Jeżeli zainteresuje Was ten temat, to w internecie jest cała masa różnego rodzaju artykułów na ten temat, ale czasami najtrudniej jest po prostu zacząć. 🙂 Ze swojej strony będę chciał jednak przygotować cykl artykułów, które pozwolą na pisanie mniej lub bardziej zaawansowanych testów.
Powiem też bardzo otwarcie, że nie uważam się za osobę, która posiada ogromną wiedzę w tej dziedzinie, natomiast bazując na obecnych doświadczeniach oraz korzystając z wielu ciekawych źródeł, postaram się przekazać wiedzę jak najlepiej. Standardowo skorzystam z praktycznych przykładów, gdyż tak jak wielokrotnie wspominałem – uważam taką formę nauki za najbardziej skuteczną.
Instalacja, pierwszy test
Skorzystamy z create-react-app (https://github.com/facebook/create-react-app), aby szybko „postawić” nową aplikację React.
npx create-react-app demo_test
Ponieważ startowa aplikacja create-react-app
posiada napisany test do komponentu App, to w zasadzie możemy już uruchomić testy poleceniem:
npm test
W wyniku uruchomienia tego polecenia, otrzymamy rezultat:
> npm test PASS src/App.test.js √ renders learn react link (55 ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 4.425 s Ran all test suites.
Jak widzimy, został uruchomiony test zlokalizowany w src/App.test.js, został wykonany jeden test, który zakończył się sukcesem, a całość trwała ponad 4 sekundy.
Nazwa pliku i struktura folderów
W tym momencie warto zwrócić uwagę na nazwę pliku App.test.js
, dla komponentu App.js
.
Jedną z rekomendowanych metod nazewnictwa jest NazwaKomponentu.test.js
, która powinna być zlokalizowana w strukturze „obok” testowanego komponentu. Celowo „obok” umieściłem w cudzysłowie, bo podejść może być kilka i zależy to od struktury projektu i jego złożoności.
Więcej na ten temat możemy przeczytać tutaj: https://create-react-app.dev/docs/running-tests/#filename-conventions
Polecam też artykuł pana Robina Wieruch dotyczący struktury folderów https://www.robinwieruch.de/react-folder-structure
Polecam kliknąć CTRL + F (wyszukiwanie tekstu) i wpisanie słowa test
Jeżeli chodzi o i mnie, pracując przy jednym projekcie struktura testów wyglądała następująco…
W folderze posiadamy:
- komponent
Counter.js
, a test do komponentu znajduje się w folderze__tests__/Counter.test.js
- plik utils w folderze
/utils/table.js
, a test znajduje się w folderze__tests__/utils/table.test.js
- jakiś inny plik znajdujący się w folderze
logic/counter/abcdef/xyz.js
, a test znajdujący się w folderze__tests__/logic/counter/abcdef/xyz.js
Oczywiście wskazane jako przykład komponenty jak i inne pliki mogą być położone w innych folderach, natomiast folder __tests__
znajdował się obok wskazanych plików.
Struktura pliku z testami
Przyjrzyjmy się teraz strukturze pliku App.test.js
i metodzie test()
.
test('renders learn react link', () => { render(<App />); const linkElement = screen.getByText(/learn react/i); expect(linkElement).toBeInTheDocument(); });
Pierwszy argument to nazwa testu, drugi zaś, to anonimowa funkcja, uruchamiana podczas testów. Tutaj zwrócę uwagę, aby nazywać testy w taki sposób, aby szybko można było stwierdzić co dany test robi i czego oczekujemy od testu. Nazwa ta będzie wyświetlana również, w przypadku niepowodzenia testu.
Zmieńmy zatem test, aby zwracał błąd, modyfikując linię
const linkElement = screen.getByText(/learn react/i);
na dowolny inny ciąg znaków, który nie występuje w komponencie, np. learn Angular
😉
Ponowne uruchomienie npm test
zwróci nam błąd, a nazwa testu zostanie wyświetlona:
> npm test FAIL src/App.test.js × renders learn react link (60 ms) ● renders learn react link Test Suites: 1 failed, 1 total Tests: 1 failed, 1 total Snapshots: 0 total Time: 4.702 s Ran all test suites.
W komunikacie jest też więcej informacji, mianowicie wskazane jest miejsce, w którym test nie wykonał się poprawnie. Nie wklejałem tego do artykułu celowo (za dużo tekstu…), ale wykonując polecenia na własnym komputerze, na pewno zauważycie różnicę. Polecam prześledzić, co wyświetla npm test
.
W przypadku metody test()
, chcę też wspomnieć o metodzie describe()
, która pomaga grupować testy. Na przykład, gdy chcemy przetestować jakąś część komponentu/funkcji i napisać do niej kilka testów, następnie chcemy przetestować inną cześć i tutaj też napisać kilka innych testów możemy pogrupować testy. Tak naprawdę sposób grupowania zależy już od nas…
describe('Check App component for text', () => { test('renders learn react link - learn React', () => { render(<App />); const linkElement = screen.getByText(/learn React/i); expect(linkElement).toBeInTheDocument(); }); test('renders learn react link - learn Angular', () => { render(<App />); const linkElement = screen.getByText(/learn Angular/i); expect(linkElement).toBeInTheDocument(); }); });
Teraz npm test
da nam wynik:
FAIL src/App.test.js Check App component for text √ renders learn react link - learn React (56 ms) × renders learn react link - learn Angular (15 ms) ● Check App component for text › renders learn react link - learn Angular Test Suites: 1 failed, 1 total Tests: 1 failed, 1 passed, 2 total Snapshots: 0 total Time: 6.25 s Ran all test suites related to changed files.
Podsumowanie
Z artykułu dowiedzieliśmy się jak uruchamiać testy, jak nazywać pliki, jaką strukturę folderów zastosować, dlatego kolejnym krokiem będzie już pisanie pierwszych testów.
Podsumujmy jednak najważniejsze kwestie:
npm test
uruchamia testy,- pamiętajmy o poprawnym nazewnictwie plików np. KomponentNazwa.test.js,
- pamiętajmy o poprawnej strukturze folderów,
- nazywajmy testy w odpowiedni sposób, aby nazwa wskazywała co test sprawdza i czego oczekujemy od testu,
- korzystajmy z grupowania testów.
Jako, że artykuł jest wstępem do testowania (a jak wiadomo wstęp nie może być za długi, bo staje się nudny 🙂 ), to by było tyle na dzisiaj… Zapraszam do następnych artykułów, gdzie na pewno będzie kolejna dawka wiedzy, już bardziej praktycznej. Dzięki!
Źródła:
Obraz: https://unsplash.com/photos/WC6MJ0kRzGw
create-react-app: https://github.com/facebook/create-react-app
nazewnictwo plików: https://create-react-app.dev/docs/running-tests/#filename-conventions
struktura folderów wg. R. Wieruch: https://www.robinwieruch.de/react-folder-structure