Cypress – Testy E2E w JavaScript

Cypress wprowadzenie

Ostatnio Mateusz poruszył temat testowania w oparciu o bibliotekę JEST. W związku z tym dzisiaj chciałabym podzielić się z wami tym czego się dowiedziałam i opowiedzieć troszkę o wrażeniach z pisania testów z użyciem Cypress. Ale zacznijmy od początku…

Cypress – czyli o co chodzi z tym cyprysem

W dużym skrócie – Cypress to javascriptowy framework przede wszystkim do testów end to end. Twórcy tego frameworka zapewniają nas, że dzięki niemu: konfiguracja, tworzenie, uruchamianie oraz debugowanie testów będzie proste. Czy aby na pewno?

Idea cypressa jest zbliżona do koncepcji JEST – to znaczy zebranie wszystkich niezbędnych narzędzi takich jak framework, biblioteki asercji, wrappera czy dodatkowych bibliotek w jeden tool.

Co odróżnia cypressa od innych narzędzi?

  • Nie opiera się na Selenium – zbudowany jest na nowej architekturze. Cypress działa w tej samej pętli uruchomieniowej, co twoja aplikacja.
  • Koncentruje się na sprawnym wykonywaniu testów – jego użycie jest intuicyjne i proste.
  • Jest uniwersalny – działa prawdopodobnie na wszystkim co może być uruchomione w przeglądarce. Dobrze powinien sobie poradzić nawet na starszych aplikacjach, nie tylko tych używających nowoczesnych frameworków.
  • Testy są pisane w javascripcie – dla jednych wada dla innych zaleta ale cypress jest oparty na javascripcie.
  • Wszystko czego potrzeba w 1 narzędziu – Nie trzeba instalować osobnych narzędzi aby uruchomić testy.
  • Narzędzie zarówno dla programistów jak i QA.
  • Cypress jest szybki – pozwala na równoczesny development i testowanie.

Tyle teorii i zapewnień twórców… W tym artykule przedstawię wam podstawy użytkowania tego narzędzia.

A! Jeszcze jedno … Cypress oferuje test runner (opensource) oraz funkcję dashboardu (częściowo bezpłatną, ale są i płatne plany). Test runner pozwala nam podejrzeć status testów, w łatwy sposób zmienić rozmiar okna (viewport), podgląd logów na bieżąco, podgląd aplikacji czyli co się aktualnie z aplikacją dzieje, jak się ona zachowuje.

Z dashboardem się jeszcze nie zaprzyjaźniłam jeśli mam być szczera. Z tego co widzę to cypress oferuje wsparcie do zarządzania w oparciu o CI, możliwość nagrywania testów, wykonywanie testów równolegle, uruchamianie grup testów (kilka uruchomień testów, może być oznaczonych i powiązanych do pojedynczego uruchomienia).

No to start – Instalacja

Instalacja Cypressa nie wydaje się niczym skomplikowanym, tym bardziej jeśli miało się już do czynienia z instalacją z użyciem npm.
Przejdź do swojego projektu:

cd /sciezkaTwojegoProjektu/

Zainstaluj cypressa poleceniem:

npm install cypress --save-dev

W ten sposób instalujemy najnowszą wersję cypressa lokalnie. I tak naprawdę, gdy instalacja dobiegnie do końca możemy zacząć działać. Możemy też ściągnąć paczkę instalacyjną ze strony cypress.io. Jednakże instalacja z konsoli jest dużo szybsza i wygodniejsza.

Po zainstalowaniu w folderze projektu pojawi się folder node_modules oraz plik package-lock.json.

By uruchomić Cypressa wystarczy użyć komendy:

node_modules\\.bin\cypress open

Efektem wykonania tego polecenia powinno być uruchomienie Test Runnera.
Po kliknięciu przycisku ‘OK, got it’ który się pojawił na ekranie runnera pojawi się stworzona struktura danych w naszym folderze projektowym. Niech to będzie nasza baza do nauki Cypressa.

Struktura plików

To jeszcze słów kilka o strukturze. Stworzone zostały 4 główne katalogi, które są godne uwagi:

  • Fixtures – pliki które zawierają statyczne dane, mogące być użyte podczas testów. Zwykle odnosimy się do nich z użyciem cy.fixture(). Używamy gdy chcemy przetestować funkcjonalność opartą na żądaniach sieciowych (xhr,/ ajax) , framework może sztucznie wstawić dane podczas testu czyli pełnić rolę Stub’a.
  • Test files – pliki testów domyślnie są umiejscowione w folderze integration. Cypress wygenerował dodatkowo folder examples z przykładami użycia.
  • Plugin files – umożliwiają korzystanie, modyfikowanie, rozszerzanie wewnętrznych zachowań frameworku. Domyślnie Cypress używa pluginów zawartych w katalogu plugins w pliku index.js. Można również pobrać bardzo dużo pluginów dostępnych na stronie cypress, często współtworzonych przez użytkowników.
  • Support files – tu można wrzucać reużywalne funkcje, niestandardowe polecenia itp które mają być dostępne dla wszystkich plików testowych.

Test runner

Na starcie warto zapoznać się ze środowiskiem uruchomieniowym. Test runner od cypressa wydaje się być całkiem przyjazny dla użytkownika, dosyć intuicyjny.

W widoku runnera możemy wybrać sobie przeglądarkę w której będzie wykonywany zestaw testów. Aktualnie wspierane przeglądarki to Canary, Chrome, Chromium, Electron. Z pewnością brakuje wparcia dla przeglądarek takich jak Firefox, Safari, Edge. Producent twierdzi że ma w planach rozwoju frameworku rozszerzać support ale … póki co tego nie oferuje, co niestety jest pewnym minusem.

Pewne słówko o Electronie – to przeglądarka, która może być uruchomiona w trybie headless. Jest wbudowana w cypressa, nie potrzeba dodatkowej instalacji. Może być bardzo użyteczna gdy uruchamiamy testy na CI. Domyślnie działa gdy uruchomimy komendę z poziomu linii poleceń

cypress run

Electron uruchomi się automatycznie, w trybie headless.

Runner podzielony jest na 3 części:
Tests – lista testów do wykonania, użytkownik może sobie konfigurować które testy mają być wykonane. Zarówno w widoku runnera jak i z poziomu ustawień.
Runs – sekcja która jest używana po podpięciu Cypress Dashboard.W tej sekcji będą widoczne testy które zostały nagrane.
Settings – w tej sekcji wyświetlana jest konfiguracja używana podczas testów, którą możemy oczywiście modyfikować za pomocą pliku cypress.json, który to domyślnie jest pusty.

Tip:

Aby ułatwić sobie pracę z cypressem z pewnością warto w pliku package.json dodać sobie wpis który umożliwi nam proste uruchamianie runnera, bądź testów za pomocą electrona.

{
  "scripts": {
    "cypress:open": "cypress open",
    "cypress:run": "cypress run"
  }
}

Z pewnością zdążyliście sami zauważyć cypress open powoduje otwarcie runnera, cypress run uruchamia testy (domyślnie w Electronie).

Piszemy pierwszy test

Gdy mamy zainstalowanego cypressa, wiemy jak wygląda test runner, możemy zacząć pisać pierwszy test.
W katalogu Integration stwórzmy sobie obok folderu examples, folder “tests” w którym będą znajdować się nasze testy. W tym katalogu utwórz plik firstTest_spec.js
Jeśli zostawiliście runnera otwartego – folder wraz z naszym plikiem testowym powinien się pojawić na liście.

Mamy plik, cypress go zobaczył – pora napisać test. Podejście co do struktury plików jest zaczerpnięte z Mocha.js Opisujemy testy za pomocą elementów descibe() oraz it().
Również możemy używać elementów z Chai np. expect. Nie musimy tego dodatkowo instalować, jest to wbudowane w Cypress.

Otwórzmy plik i napiszmy dwa testy. Jeden powinien być ukończony z pozytywnym rezultatem, drugi już nie.

describe('Our first test', function () {
   it('It should pass', function () {
       expect(2).to.equal(2)
   });

   it('It should fail', function () {
       expect(2).to.equal(5)
   })
});

Gdy mamy takie dwa proste testy możemy uruchomić nasze dzieło. W tym celu przechodzimy do runnera na drzewie testów szukamy naszego pliku i klikamy w niego by go uruchomić.

Tu należy jeszcze wspomnieć – na ekranie pojawia się nowe okno przeglądarki. Podzielone na 2 części. Z lewej strony widzimy listę testów i rezultaty ich wykonania.Gdy najedziemy na każde polecenie bądź asercję, zostaniemy przeniesieni do właściwego miejsca w podglądzie testu. Pozwala nam to łatwo podglądać co dokładnie się działo podczas wykonywania testu. W drugiej części strony widzimy wspomniany już podgląd. Nasz test póki co nie ma zbytnio co pokazywać więc widzimy tylko rezultat testów. Zgodnie z oczekiwaniami. Jeden test zaliczony, drugi nie. W przypadku tego drugiego też widzimy co poszło nie tak.

Gdy wprowadzimy zmiany w naszym teście, na przykład gdy dopiszemy kolejny test i zapisujemy zmiany w pliku, automatycznie zestaw testów powinien się wykonać ponownie z uwzględnieniem nowego testu.

Bardziej realny test

Spróbujmy teraz napisać taki test by jego działanie było widoczne w przeglądarce. Najprostszym testem będzie otwarcie przeglądarki i weryfikacja czy URL jest prawidłowy. Dlatego też stwórzmy kolejny plik testowy w naszym katalogu integration/tests np. uiTest_spec.js. Powinien on się pojawić w naszym runnerze.
Teraz musimy stworzyć nasz test, będzie on bardzo prosty – będzie otwierać wybraną stronę i weryfikować czy adres url się zgadza.

describe('Cypress.io tests', function() {
   it('Open cypress.io page', function() {
     var cypressPage = 'https://www.cypress.io/'
     cy.visit(cypressPage)
     cy.url().should('include', cypressPage);
   })
 })

Po zapisaniu zmian i uruchomieniu testów pojawi się znowu okno wykonywania testów ale tutaj już będziemy widzieć jak jak program sam “klika” po aplikacji.

Z lewej strony ekranu tak jak poprzednio widzimy przebieg testu oraz wynik asercji. Po prawej z kolei już mamy podgląd stanu aplikacji w danym momencie. Co więcej, gdy otworzymy konsole deweloperską (F12) i klikniemy w element testu w kolumnie po lewej stronie np. URL to w konsoli pojawią się szczegóły zapytania.

Jak widać test przeszedł. No to trochę go rozbudujemy. Dopiszmy do testu kolejną linijkę

cy.contains('see more features')

Test przeszedł, pomimo że nie mamy w zasadzie napisanej asercji. Cypress jest tak skonstruowany by testy zawiodły jeśli nie znajdą tego czego potrzebują.

A gdyby tak chcieć kliknąć od razu w ten element?
Wystarczy dodać akcje kliku na koniec tego co aktualnie napisaliśmy. Powinno wyglądać to tak:

cy.contains('see more features').click();

Efektem powinno być otwarcie nowej strony z opisem ‘ficzerów’.
Możemy też do tego podejść z użyciem cy.get np stosując do tego samego elementu inne podejście do znalezienia elementu:

cy.get('[href="/features"]');
cy.get('[aria-label="see-more-features"]');

Jak widzicie możemy wynajdywać 1 element na kilka sposobów. Jest to bardzo wygodne, czasami używając innych frameworków trudno jest dobrać metodę by dostać się do konkretnego elementu. Tutaj jest to banalnie proste.

Upewnijmy się że strona została poprawnie otwarta, dodamy asercję którą już znacie:

cy.url().should('include', '/features');

I możemy sprawdzić czy dwa elementy spodziewane są faktycznie na stronie

cy.contains('A test runner built for humans')
cy.contains('An open source, front-end testing tool, built for the modern web.')

No to na koniec jeszcze spróbujmy w pole email wpisać swój mail i zweryfikować czy aby na pewno taka wartość została wpisana
Zrobimy to bardzo szybko wystarczy połączyć wyszukanie elementu + wpisywanie i od razu asercję w ramach jednej linii kodu.

cy.get('input[type="email"]').type('[email protected]').should('have.value','[email protected]')

Konstrukcje get znacie chociaż tutaj jasno określiłam rodzaj elementu jako input, ale równie często może być to np. button.
Type pozwala nam na wprowadzenie tekstu do wybranego pola.
Zaś should jest asercją znaną z Chai.

Spróbujcie wykonać ten test – powinien nie przejść. Ponieważ to co wpisałam w inpucie jest różne od warunku sprawdzającego. Cypress zwraca nam uwagę w wyniku testów, że spodziewał się ‘[email protected]’ a dostal ‘[email protected]’. Warto to później poprawić tak by oba maile były zgodne.

Finalnie nasz test powinien wyglądać mniej więcej tak:

describe('Cypress.io tests', function() {
   it('Open cypress.io page', function() {
     var cypressPage = 'https://www.cypress.io/'
     cy.visit(cypressPage)
     cy.url().should('include', cypressPage);
     cy.get('[href="/features"]');
     cy.get('[aria-label="see-more-features"]');
     cy.contains('See more features').click();
     cy.url().should('include', '/features');
     cy.contains('A test runner built for humans')
     cy.contains('An open source, front-end testing tool, built for the modern web.')
     cy.get('input[type="email"]').type('[email protected]').should('have.value','[email protected]')
   })
 })

Podsumowanie

Podczas napisanego przez nas testu przeszliśmy do strony, sprawdziliśmy czy trafiliśmy pod dobry adres, znaleźliśmy na kilka sposobów czy zawiera link do sekcji Feature, przeszliśmy do wspomnianej sekcji, zapewniliśmy, że trafiliśmy na dobrą stronę, zweryfikowaliśmy elementy na stronie i za jednym razem wprowadziliśmy swój email do formularza i zweryfikowaliśmy czy zgadza się z zawartością.
Tak naprawdę jest to tylko ułamek możliwości Cypressa, które postaram się Wam w następnych artykułach przedstawić.

Ponadto już dziś zapraszam Was do lektury kolejnych artykułów na temat cypressa gdzie z pewnością pojawią się informacje na temat sposobu zarządzania testami czy też konfiguracji, generowania raportów oraz omówienie bardziej złożonych możliwości tego frameworka i wiele wiele innych.

Na codzień pracuje jako Senior Quality Assurance Engineer. Testowanie to jest to co lubi najbardziej. Prywatnie kocha gotować, grać w gry planszowe i podróżować. Jest niepoprawną kociarą.
PODZIEL SIĘ