Snapshot testing, czyli testowanie aplikacji frontendowych za pomocą snapshotów

    Od kilku lat można zauważyć, że aplikacje frontendowe stają się coraz większe i skomplikowane. W utrzymaniu dużych aplikacji oraz unikaniu wprowadzania błędów przy ich rozbudowie z pewnością przydatne jest pisanie testów. Mogą one obejmować nie tylko logikę biznesową, ale także sprawdzać kod HTML. Testy z użyciem snapshotów dostępne we frameworkach Karma oraz Jest dają dodatkową korzyść -  pozwalają na wykrycie regresji podczas tworzenia kodu.

 

Główna idea przyświecająca snapshot testing

Snapshot (po polsku - migawka), to test pokazujący drzewo DOM dla testowanego komponentu w określonym stanie i ze specyficznymi danymi. Testy można tworzyć z użyciem sekcji given, when, then.

  • Given - ustawienie testu i danych
  • When - uruchamiana jest akcja
  • Then - sprawdzamy wynik testu z użyciem asercji

W ostatniej sekcji testu sprawdzamy, czy obecny snapshot, jest taki sam, jak ten, który znajduje się w repozytorium. Gdy tak nie jest, oznacza to, że wprowadziliśmy albo niepotrzebną regresję, albo że zmiany są potrzebne i snapshot można zastąpić nowym.

 

Snapshoty można tworzyć na kilka sposobów. IDE, jak np. Intellij Idea, pozwala na włączenie testów tworzących snapshoty z poziomu kodu testu (oddzielnie dla każdego) lub pliku z testami. Jeśli wygenerowany snapshot różni się od poprzedniego, możemy go odrzucić lub zaakceptować. Następnie należy włączyć testy w całym repozytorium, na przykład za pomocą komendy npm, by upewnić się, że regresja nie powstała nigdzie indziej.

 

Snapshoty traktuje się tak, jak zwykły kod - znajdują się one w repozytorium i powinny być sprawdzane podczas code review. Dzięki temu, można wykrywać różnice w HTML, porównując kod z poprzednią wersją, bez konieczności sprawdzania aplikacji w przeglądarce. Nie zastępuje to testów regresyjnych, ale pozwala wykryć przypadkowo wprowadzone zmiany już podczas rozwoju kodu lub code review.

 

Framework Jest umożliwia także podbicie snapshotów w całej aplikacji za pomocą polecenia jest -u. Jest to pomocne, gdy wykonywaliśmy zmianę w komponencie wykorzystywanym w wielu miejscach lub refaktoryzowaliśmy globalny kod. W takiej sytuacji, podbijamy wszystkie snapshoty automatycznie, a następnie porównujemy różnice z poprzednią wersją z użyciem narzędzi do kontroli wersji. Jeśli nie ma powodów do niepokoju, snapshoty można dodać do repozytorium. Gdy zauważymy niepotrzebne zmiany, należy w pierwszej kolejności przyjrzeć się, czy kod i dane testowe są prawidłowe.

Warto pamiętać, że Intellij Idea może nie widzieć zmian dokonanych z użyciem innego narzędzia wywoływanego z poziomu konsoli. Aby je zobaczyć, trzeba użyć opcji “Reload all from disk” z menu File. To szczególnie przydatne, gdy wykorzystujemy wbudowane w IDE narzędzia do kontroli wersji.

 

Na co należy zwrócić uwagę podczas testów?

Snapshoty powinny obejmować jak najwięcej przypadków testowych. Przykładowo - możliwe jest zamockowanie danych dla:

  • zwrotki z pełnymi danymi
  • błędu z serwera
  • pustej odpowiedzi serwera
  • konieczności pokazania na stronie dodatkowych elementów, jak na przykład okna modalne

Im większe będzie pokrycie przypadków, tym łatwiej jest później wychwycić nieprawidłowości przy zmianach kodu. Test pokrywający tylko przypadek pozytywny, jest mało miarodajny, ponieważ regresja może objawiać się w przypadkach skrajnych. W praktyce każda zmiana kodu HTML lub JS odpowiedzialnego za wyświetlanie kodu w pewnych przypadkach, powinna powodować konieczność podbicia snapshotów. Jeśli zmieniamy coś w kodzie HTML, a nie zauważyliśmy zmiany snapshota, prawdopodobnie konieczne jest dopisanie przypadku testowego.

 

Ważną kwestią jest dbanie o aktualność snapshotów. Czasem dochodzi do sytuacji, gdy włączenie wszystkich testów informuje nas o obsolete (przestarzałych) snapshotach. Pojawiają się one, gdy na przykład usunęliśmy test, ale w pliku snapshota został kod dotyczący usuniętego przypadku testowego. Można wtedy na przykład wygenerować snapshot ponownie z użyciem jest, albo usunąć go i wygenerować ponownie.

 

Podczas analizy snapshotów, zwracamy uwagę na to, czy:

  • nie doszło do poważnej zmiany snapshota bez potrzeby (mała zmiana w kodzie, duża w snapshocie)
  • czy nie występują miejsca z pustymi lub nieprawidłowo sformatowanymi danymi (być może dane testowe są nieprawidłowe)
  • czy nie powinniśmy dodać kolejnego testu, zwłaszcza, gdy tworzymy nowe funkcjonalności, lub zauważymy niepokryty przypadek.

Snapshoty nie powinny być zmieniane ręcznie. Aby ułatwić sobie analizę snapshotów, warto włączyć w edytorze dla tego formatu pliku kolorowanie składni HTML.

W niektórych przypadkach snapshoty będą mało optymalnym rozwiązaniem. Wygenerowanie snapshota jest dość obciążające dla maszyny, a odpalenie testów dla całej aplikacji, może zająć kilka minut. Jeśli testujemy np. zmianę klasy w reakcji na kliknięcie w element, lepszym wyborem będzie test sprawdzający, czy dana klasa występuje lub nie, bez generowania snapshota.

 

Włączanie części komend do testowania można powiązać z systemem kontroli wersji (np. z użyciem Husky). Dzięki temu, testy będą włączane automatycznie na przykład podczas commitowania pliku i cały flow pracy, jeszcze bardziej się uprości.

 

Podsumowując, testowanie aplikacji z użyciem snapshotów, pozwala na ograniczenie błędów regresji dzięki wprowadzeniu do projektu kilku prostych reguł dotyczących tworzenia testów.


Kamil

Programista Front-end w Nexio Management

Powrót