Wyślij zapytanie Dołącz do Sii

Testy komponentów to dość nowe pojęcie – zostały wprowadzone w Cypress w wersji 10.0.0. w czerwcu 2022. Z implementacją testów komponentów mieliśmy do czynienia już wcześniej, jednak nie na takim poziomie, na jakim jest ona realizowana obecnie.

W artykule opiszę, czym są tytułowe testy komponentów, przedstawię ich przykładową przeszłą oraz, korzystając z Cypressa, obecną implementację. Dodatkowo omówię wady i zalety tych rozwiązań.

Jeżeli jesteście zainteresowani tematyką Cypressa, serdecznie zapraszam do zapoznania się z moim poprzednim artykułem: Testy automatyczne: Cypress czeka aż… – wprowadzenie do waitów oraz z artykułem mojego kolegi Michała: Cypress – dlaczego warto zainteresować się tym frameworkiem?

Testy komponentów – czym są?

Testy komponentów w obszarze testowania front-end odnoszą się do praktyki sprawdzania pojedynczych komponentów lub jednostek aplikacji internetowej w izolacji. Głównym celem jest zapewnienie, że każdy komponent zadziała zgodnie z oczekiwaniami, już we wczesnej fazie rozwoju.

Komponenty w tym kontekście to zazwyczaj mniejsze, niezależne fragmenty interfejsu użytkownika, takie jak:

  • przyciski,
  • formularze,
  • niestandardowe elementy interfejsu.

Przykładowo – popularny „date-picker” idealnie wpisuje się w tę definicję i stanowi doskonały przedmiot sprawdzenia testów na „własnej klawiaturze”.

Korzyści wynikające z testów

Testy te przynoszą szereg korzyści, a ich krótka charakterystyka jest następująca:

  • Testy w izolacji – oznacza to, że nie potrzebujemy rzeczywistego działającego oprogramowania, serwisu, strony internetowej ani serwera, aby przeprowadzić test. Dzięki temu zyskujemy zarówno na czasie, jak i na stabilności tych testów.
  • Małe i szybkie testy – przeprowadzamy testy komponentów prawie tak samo, jak testy jednostkowe. To pozwala nam w szybki sposób wykryć ewentualne nieprawidłowości, co skutkuje wczesną i stosunkowo niedrogą naprawą.
  • Łatwy i czytelny kod – przy użyciu tej praktyki wprowadzamy łatwość utrzymania kodu i zwiększamy jego przejrzystość. Aplikacja jest podzielona na mniejsze części, które są następnie testowane przez te właśnie komponentowe testy.
  • Automatyzacja i integracja – testy te można z łatwością zautomatyzować i włączyć w narzędzia do ciągłej integracji. Mamy możliwość uruchamiać je lokalnie na kontenerze Docker, co jest szczególnie przydatne, gdy dopiero rozpoczynamy swoją przygodę z testami automatycznymi.

Ale po co nam właściwie testy komponentów?

Aby odpowiedzieć na to pytanie, zapoznamy się z potrzebą oraz istotą testów automatycznych.

Test automatyczny to część procesu, w którym sprawdzamy scenariusze testowe za pomocą narzędzi do automatyzacji lub skryptów. Ważne jest jednak pamiętanie o podstawach testowania, ponieważ są one kluczowe przy tworzeniu przypadków testowych.

W moim przekonaniu, dobry test automatyczny powinien składać się z trzech elementów:

  1. danych testowych,
  2. kroków,
  3. jednej asercji.

Stawiając to ostatnie jako istotne kryterium, poruszam dość kontrowersyjny temat. Test, który sprawdza wiele rzeczy – moim zdaniem – jest niezbyt wiarygodny, trudny w utrzymaniu i weryfikacji.

Przyjrzyjmy się sytuacji, gdzie chcemy napisać test, który wysyła formularz rejestracji użytkownika. Wypełniamy wszystkie pola i klikamy przycisk „wyślij” za pomocą cy.contains(„wyślij”). Pojawia się jednak pytanie – co się stanie, jeśli nasz przycisk ma inny tekst, na przykład z powodu problemów z wyświetlaniem polskich znaków? Otrzymujemy wynik negatywny w teście, który tworzy użytkownika, pomimo że ciąg znaków (popularnie nazywany stringiem), po którym szukamy przycisku, jest inny.

Co możemy zrobić w tej sytuacji? Napisać lepszy test! Możemy użyć metody cy.get() i podać tutaj nasz unikalny identyfikator (cy-data lokator). Ten sposób eliminuje konieczność wyszukiwania elementów po konkretnym ciągu znaków i odnosi się do lokatora. Jednakże, zdarza się, że korzystamy z metody cy.contains(), ponieważ jest to bardziej wygodne i efektywne, niż w przypadku użycia metody cy.get().

Co jednak, jeśli mielibyśmy test komponentu, który generuje ten element z oczekiwanym ciągiem znaków, sprawdzając jednocześnie jego tekst, zachowanie i style CSS?

Nasze narzędzie do ciągłej integracji nie pozwoliłoby na uruchomienie kolejnych testów bez naprawy tego, co daje wynik negatywny. Dzięki wczesnemu wykryciu błędu, możemy szybko i tanio go naprawić. Dodatkowo, dzięki temu unikniemy fałszywie negatywnych wyników w pozostałych testach, gdzie to właśnie komponent jest winny, a nie logika samego kodu.

Testy komponentów a piramida testów

Piramida testów jest to „wzorzec projektowy”, który przedstawia nam kolejność testów oraz ich ilości. Zgodnie z ogólnie przyjętą normą, dzieli się ona na trzy poziomy. Są one ułożone jeden na drugim, w kolejności względem kosztu stworzenia/utrzymania, czy też samego czasu wykonania.

Piramida testów przedstawiająca 3 główne poziomy testów
Ryc. 1 Piramida testów przedstawiająca 3 główne poziomy testów

Unit testy

Unit testy czyli testy jednostkowe – w większości przypadków pisane przez developerów. Mają one za zadanie sprawdzić metodę/funkcję/moduł na poziomie jednostkowym. Powinny mieć jak największe, realne pokrycie kodu.

Przedstawia się je jako podstawę/fundament piramidy testów, ponieważ są:

  • niezależne od zewnętrznych serwisów,
  • niezwykle szybkie do napisania i wykonania,
  • tanie w utrzymaniu i tworzeniu,

Ponadto, mogą też być traktowane jako swojego rodzaju dokumentacja projektowa.

Testy integracyjne

Na kolejnym poziomie znajdują się testy integracyjne, w których skład wchodzą testy:

  • systemowe,
  • integracyjne.

Sprawdzają one, czy poszczególne moduły ze sobą rozmawiają – zarówno z danymi testowymi, jak i realnymi. Pisane i wykonywane są głównie przez testerów, ale to też zależy od ustaleń w danym zespole oraz od podejścia projektowego. Mogą być uzależnione od zewnętrznych serwisów, w zależności od skomplikowania, jednak są zdecydowanie tańsze oraz szybsze od testów E2E.

Testy End-to-End

Testy E2E sprawdzają ścieżki biznesowe, zaczynając od stworzenia użytkownika, poprzez zakup przedmiotu w sklepie internetowym. Jednak posiadają następujące wady:

  • są niestabilne,
  • są bardzo drogie w tworzeniu i utrzymaniu,
  • pokrywają znikomą część kodu,
  • czas wykonania tych testów jest dużo dłuższy niż testów jednostkowych, czy też integracyjnych.

A gdzie są testy komponentów w piramidzie testów?

Po tym, co przeczytaliście o samych testach komponentów, jak i piramidzie testów, możecie wydedukować, że testy komponentów znajdują się pomiędzy warstwą jednostkową a integracyjną. I dokładnie w tym miejscu ja je umieszczam.

Piramida testów z umiejscowieniem testów komponentów
Ryc. 2 Piramida testów z umiejscowieniem testów komponentów

Kto powinien pisać/tworzyć testy komponentów?

Powstaje pytanie o to, kto powinien tworzyć testy komponentów. Sytuacja jest podobna, jak w przypadku testów jednostkowych. Źródła internetowe twierdzą, że za testy komponentów odpowiedzialni sią deweloperzy, jednak z doświadczenia wiem, że większość z nich skupia się bardziej na implementacji kodu, niż pisaniu testów. Jest to również dyskusyjny temat związany z definicją ukończenia, z podejściem projektowym oraz zespołowym.

Moim zdaniem pisanie testów komponentów to idealne zadanie dla testera, który chce rozpocząć swoją przygodę z testami automatycznymi, ponieważ są one łatwe w przygotowaniu i utrzymaniu, a ich wyniki są bardzo czytelne, rzetelne i transparentne.

Testy komponentów w praktyce

Przedstawię i omówię dwa podejścia – stary i nowy sposób tworzenia testów komponentów wraz z ich implementacją w języku JavaScript z wykorzystaniem Cypressa.

Old-fashion way

Stare podejście – spotykane nie tylko w Cypressie, ale również w innych frameworkach testowych, gdzie nie mamy obecnie możliwości wyświetlania komponentów. Znając ograniczenia, postarajmy się to zaimplementować.

Chcemy, aby test sprawdził, czy przycisk „Click me” na stronie spełnia oczekiwania. Weryfikujemy to na naszej uruchomionej lokalnej wersji tworzonego oprogramowania pod adresem http://localhost:4200/:

Weryfikacja działania przycisku „Click me”
Ryc. 3 Weryfikacja działania przycisku „Click me”

Tworzymy przypadki testowe i sprawdzamy, czy to działa:

  1. Sprawdź, czy przycisk ma napis „Click me”.
  2. Sprawdź, czy przycisk ma czerwony kolor tła.
  3. Sprawdź, czy przycisk wyświetla poprawnie text 1!2#45.
  4. Sprawdź, czy przycisk wyświetla poprawnie zmieniony kolor na niebieski.
kod

Przedstawiony kod wygląda schludnie i czytelnie. Przy zastosowaniu wzorca projektowego Page-Object i wyciagnięciu do zmiennych powtarzających się elementów, możemy uzyskać jeszcze bardziej przejrzysty kod. Jego wadą niewątpliwie jest czas wykonywania, który przy czterech testach wynosi tylko, albo aż, 809ms.

Musimy zwrócić uwagę na to, że do przycisku dostajemy się natychmiast po załadowaniu „localhosta”. Nie wymaga on żadnej dodatkowe interakcji, co przy czterech przypadkach testowych pozwala nam osiągnąć akceptowalny czas. Jednakże bardziej skomplikowane jest wyodrębnienie poszczególnych elementów. Przykładowo – edycji użytkownika z trzeciej strony formularza, aby dotrzeć do przycisku reset, który jednak pojawia się dopiero po dokonaniu edycji dowolnego pola.

I nagle test wygląda tak:

kod

W takim przypadku istnieje zagrożenie, że stracimy sporo czasu na pozyskanie tego elementu, co może prowadzić do znacznego wzrostu kodu oraz uzależnienia od innych serwisów.

Co by się stało, gdybyśmy sprawdzili przycisk na „produkcyjnym” serwerze? Wykonanie tych czterech testów zajęło mi 12 sekund.

Co możemy zrobić, aby nasz test był lepszy i szybszy?

Co warto uwzględnić, by testy były bardziej efektywne:

  1. Jeżeli mamy StoryBooka lub inne podobne narzędzie, napiszmy testy w tym narzędziu. Możemy napotkać nieprzyjemności z Iframe, jednak ich skala jest drastycznie mniejsza do czasu uruchomienia tych testów. Ponadto są one bardzo zbliżone do samych testów komponentów.
  2. Połączmy wszystkie asercje w jednym teście, korzystając z tzw. Soft asercji (asercja, która w monecie wystąpienia nie przerywa testu), aby zaoszczędzić czas podczas odwiedzania strony lub elementu. Pomysł ten może być korzystny, zwłaszcza z odpowiednim reporterem, co może naprawdę zaowocować. (Jest to potencjalny antywzorzec, ponieważ test powinien składać się z jednej asercji, ale… to temat na osobny wpis). Udało mi się uzyskać czas 358 ms.
  3. Nie odświeżajmy strony i wykonajmy asercje w osobnych testach (antywzorzec, ponieważ testy są zależne od siebie). Czas: 278 ms.
  4. Wykorzystajmy testy komponentów dostarczone od Cypressa z wykorzystaniem metody cy.mount()!
kod

Dzięki tej metodzie mamy możliwość wygenerowania komponentu pojedynczo poprzez jego import i przekazanie go do metody mount(). Oszczędzamy czas na pisanie i egzekucję, nasz kod jest przejrzysty, a testy wiarygodne. Czas, jaki otrzymałem, to 162 ms! Czyli najlepszy jak do tej pory.

Testy komponentów
Ryc. 4 Testy komponentów

Jeśli nie Cypress, to co?

Testowanie komponentów nie ogranicza się jedynie do narzędzia Cypress. Istnieje szereg alternatywnych narzędzi, takich jak:

  • Jest,
  • Enzyme,
  • Vue Test Utils,

które również mogą być skutecznie używane do tej praktyki.

Te różnorodne opcje pozwalają deweloperom na dostosowywanie narzędzi do konkretnych potrzeb projektu, co staje się szczególnie istotne w sytuacjach, gdy Cypress, z różnych powodów, nie spełnia oczekiwań.

***

Więcej o Cypress dowiesz się z innych artykułów naszych ekspertów.

5/5 ( głosy: 9)
Ocena:
5/5 ( głosy: 9)
Autor
Avatar
Piotr Flis

Przygodę z testami rozpoczął w 2015 roku, pracując z Silk Testem oraz Pythonem. Obecnie zajmuje się automatyzacją testów w Cypress z wykorzystaniem JavaScrypt oraz TypeScrypt. Jest założycielem grupy strzeleckiej Sii-ła Magnum w Sii. Po pracy kładzie nacisk na rozwój osobisty w zakresie testów automatycznych i praktykę strzelecką. Z dużą dozą prawdopodobieństwa można go spotkać na największych zawodach IPSC w Polsce w kategorii Strzelba Standard

Zostaw komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

  • Cześć Siwy, dziękuję za komentarz. Zadajesz mocno kontrowersyjne pytania 😉 Aby określić, co jest lepsze, musimy mieć kryteria oceny. Jeżeli pytasz, co jest łatwiejsze, ogólnie mówiąc, to uważam, że Cypress jest łatwiejszy od Selenium.

Może Cię również zainteresować

Pokaż więcej artykułów

Bądź na bieżąco

Zasubskrybuj naszego bloga i otrzymuj informacje o najnowszych wpisach.

Otrzymaj ofertę

Jeśli chcesz dowiedzieć się więcej na temat oferty Sii, skontaktuj się z nami.

Wyślij zapytanie Wyślij zapytanie

Natalia Competency Center Director

Get an offer

Dołącz do Sii

Znajdź idealną pracę – zapoznaj się z naszą ofertą rekrutacyjną i aplikuj.

Aplikuj Aplikuj

Paweł Process Owner

Join Sii

ZATWIERDŹ

This content is available only in one language version.
You will be redirected to home page.

Are you sure you want to leave this page?