1000 stóp Przegląd pisania testów na cyprys #frontend@twiliosendgrid

Opublikowany: 2020-10-03

W Twilio SendGrid napisaliśmy setki kompleksowych testów Cypress (E2E) i nadal piszemy więcej, gdy nowe funkcje są udostępniane w różnych aplikacjach internetowych i zespołach. Testy te obejmują cały stos, weryfikując, czy najczęstsze przypadki użycia, przez które przechodziłby klient, nadal działają po wprowadzeniu nowych zmian w kodzie do naszych aplikacji.

Jeśli chcesz najpierw cofnąć się o krok i przeczytać więcej o tym, jak ogólnie myśleć o testowaniu E2E, zajrzyj do tego wpisu na blogu i wróć do niego, gdy będziesz gotowy. Ten wpis na blogu nie wymaga od Ciebie bycia ekspertem w testach E2E, ale pomaga wejść w odpowiedni nastrój, ponieważ zobaczysz, dlaczego w naszych testach zrobiliśmy pewne rzeczy w określony sposób. Jeśli szukasz bardziej szczegółowego samouczka wprowadzającego do testów Cypress, zalecamy zapoznanie się z dokumentacją Cypress . W tym poście zakładamy, że być może widziałeś lub napisałeś już wiele testów Cypress i jesteś ciekawy, jak inni piszą testy Cypress dla swoich własnych aplikacji.

Po napisaniu wielu testów Cypress, zaczniesz zauważać, że używasz podobnych funkcji, asercji i wzorców Cypress, aby osiągnąć to, czego potrzebujesz. Pokażemy Ci najczęstsze części i strategie, których używaliśmy lub robiliśmy wcześniej z Cypressem, aby pisać testy dla oddzielnych środowisk, takich jak dev lub staging. Mamy nadzieję, że ten 1000-metrowy przegląd tego, jak piszemy testy Cypress, da Ci pomysły do ​​porównania z własnymi i pomoże ci ulepszyć sposób, w jaki podchodzisz do testów Cypress.

Zarys:

  1. Podsumowanie API cyprysów
  2. Interakcja z elementami
  3. Asercja na elementach
  4. Radzenie sobie z API i usługami
  5. Wykonywanie żądań HTTP za pomocą cy.request(…)
  6. Tworzenie wtyczek wielokrotnego użytku za pomocą cy.task()
  7. Szydzenie żądań sieciowych za pomocą cy.server() i cy.route()
  8. Polecenia niestandardowe
  9. O obiektach strony
  10. Rezygnacja z uruchamiania kodu po stronie klienta z window.Cypress checks
  11. Radzenie sobie z ramkami iframe
  12. Standaryzacja w środowiskach testowych

Cyprysowe podsumowanie API

Zacznijmy od omówienia części, których najczęściej używaliśmy z Cypress API.

Wybieranie elementów

Istnieje wiele sposobów wybierania elementów DOM, ale większość tego, co trzeba zrobić, można wykonać za pomocą tych poleceń Cypress i zazwyczaj można po nich łączyć więcej akcji i asercji.

  • Pobieranie elementów w oparciu o jakiś selektor CSS za pomocą cy.get(“[data-hook='someSelector']”) lub cy.find(“.selector”) .
  • Wybieranie elementów na podstawie jakiegoś tekstu, takiego jak cy.contains(“someText”) lub pobieranie elementu z określonym selektorem, który zawiera jakiś tekst, taki jak cy.contains(“.selector”, “someText”) .
  • Uzyskanie elementu rodzica, który będzie wyglądał „wewnątrz”, dzięki czemu wszystkie przyszłe zapytania będą dotyczyć dzieci rodzica, takich jak cy.get(“.selector”).within(() => { cy.get(“.child”) }) .
  • Znajdowanie listy elementów i przeglądanie „każdego” w celu wykonania większej liczby zapytań i asercji, takich jak cy.get(“tr”).each(($tableRow) => { cy.wrap($tableRow).find('td').eq(1).should(“contain”, “someText” }) .
  • Czasami elementy mogą być poza widokiem strony, więc najpierw musisz przewinąć element do widoku, np. cy.get(“.buttonFarBelow”).scrollIntoView() .
  • Czasami będziesz potrzebować dłuższego limitu czasu niż domyślny limit czasu polecenia, więc możesz opcjonalnie dodać { timeout: timeoutInMs } jak cy.get(“.someElement”, { timeout: 10000 }) .

Interakcja z elementami

Są to najczęściej używane interakcje znalezione w naszych testach Cypress. Czasami będziesz musiał dodać właściwość { force: true } w tych wywołaniach funkcji, aby ominąć niektóre sprawdzenia elementów. Dzieje się tak często, gdy element jest w jakiś sposób zakryty lub pochodzi z zewnętrznej biblioteki, nad którą nie masz dużej kontroli pod względem sposobu renderowania elementów.

  • Musimy klikać wiele rzeczy, takich jak przyciski modalne, tabele i tym podobne, więc robimy takie rzeczy jak cy.get(“.button”).click() .
  • Formularze znajdują się wszędzie w naszych aplikacjach internetowych i służą do wypełniania danych użytkownika i innych pól danych. Wpisujemy te dane wejściowe za pomocą cy.get(“input”).type(“somekeyboardtyping”) i może być konieczne wyczyszczenie niektórych domyślnych wartości danych wejściowych, usuwając je najpierw, np cy.get(“input”).clear().type(“somenewinput”) . Istnieją również fajne sposoby na wpisywanie innych klawiszy, takich jak {enter} dla klawisza Enter, gdy robisz cy.get(“input”).type(“text{enter}”) .
  • Możemy wchodzić w interakcje z wybranymi opcjami, takimi jak cy.get(“select”).select(“value”) i polami wyboru, takimi jak cy.get(“.checkbox”).check() .

Asercja na elementach

Są to typowe twierdzenia, których możesz użyć w testach Cypress, aby określić, czy na stronie znajdują się elementy o właściwej treści.

  • Aby sprawdzić, czy coś pojawia się na stronie, możesz przełączać się między cy.get(“.selector”).should(“be.visible”) i cy.get(“.selector”).should(“not.be.visible”) .
  • Aby określić, czy elementy DOM istnieją gdzieś w znaczniku i jeśli niekoniecznie obchodzi Cię, czy elementy są widoczne, możesz użyć cy.get(“.element”).should(“exist”) lub cy.get(“.element”).should(“not.exist”) .
  • Aby sprawdzić, czy element zawiera lub nie zawiera tekstu, możesz wybrać między cy.get(“button”).should(“contain”, “someText”) i cy.get(“button”).should(“not.contain”, “someText”) .
  • Aby sprawdzić, czy wejście lub przycisk jest wyłączony lub włączony, możesz potwierdzić w ten sposób: cy.get(“button”).should(“be.disabled”) .
  • Aby potwierdzić, czy coś jest zaznaczone, możesz przetestować, np. cy.get(“.checkbox”).should(“be.checked”) .
  • Zwykle możesz polegać na bardziej namacalnych kontrolach tekstu i widoczności, ale czasami musisz polegać na kontrolach klasy, takich jak cy.get(“element”).should(“have.class”, “class-name”) . Istnieją inne podobne sposoby testowania atrybutów za pomocą .should(“have.attr”, “attribute”) .
  • Często przydaje się również łączenie asercji, np. cy.get(“div”).should(“be.visible”).and(“contain”, “text”) .

Radzenie sobie z API i usługami

Kiedy masz do czynienia z własnymi API i usługami związanymi z pocztą e-mail, możesz użyć cy.request(...) do wysyłania żądań HTTP do punktów końcowych zaplecza z nagłówkami auth. Inną alternatywą jest tworzenie cy.task(...) , które można wywoływać z dowolnego pliku spec, aby objąć inne funkcje, które najlepiej można obsłużyć na serwerze Node z innymi bibliotekami, takie jak łączenie się ze skrzynką e-mail i znajdowanie dopasowywanie wiadomości e-mail lub posiadanie większej kontroli nad odpowiedziami i odpytywaniem niektórych wywołań interfejsu API przed zwróceniem niektórych wartości do użycia przez testy.

Wykonywanie żądań HTTP za pomocą cy.request(…)

Możesz użyć cy.request() , aby wysyłać żądania HTTP do swojego backendowego API w celu skonfigurowania lub usunięcia danych przed uruchomieniem przypadków testowych. Zwykle przekazujesz adres URL punktu końcowego, metodę HTTP, taką jak „GET” lub „POST”, nagłówki, a czasem treść żądania do wysłania do interfejsu API zaplecza. Następnie możesz połączyć to z .then((response) => { }) , aby uzyskać dostęp do odpowiedzi sieciowej poprzez właściwości takie jak „status” i „body”. Poniżej pokazano przykład wykonania cy.request() .

Czasami możesz nie dbać o to, czy cy.request(...) zawiedzie z kodem statusu 4xx lub 5xx podczas czyszczenia przed uruchomieniem testu. Jednym ze scenariuszy, w którym możesz zignorować kod stanu, w którym wystąpił błąd, jest sytuacja, w której test wysyła żądanie GET, aby sprawdzić, czy element nadal istnieje i został już usunięty. Element może być już wyczyszczony, a żądanie GET zakończy się niepowodzeniem z kodem stanu 404 nie znaleziono. W takim przypadku należy ustawić inną opcję failOnStatusCode: false , aby testy Cypressa nie kończyły się niepowodzeniem przed wykonaniem kroków testowych.

Tworzenie wtyczek wielokrotnego użytku za pomocą cy.task()

Gdy chcemy mieć większą elastyczność i kontrolę nad funkcją wielokrotnego użytku, aby komunikować się z inną usługą, taką jak dostawca skrzynki odbiorczej poczty e-mail za pośrednictwem serwera Node (omówimy ten przykład w późniejszym poście na blogu), lubimy zapewnić własne dodatkowe funkcje i niestandardowe odpowiedzi na API wymagają od nas połączenia i zastosowania w naszych testach Cypress. Lub lubimy uruchamiać inny kod na serwerze Node — często budujemy dla niego wtyczkę cy.task() . Funkcje wtyczek tworzymy w plikach modułów i importujemy je w plugins/index.ts , gdzie definiujemy wtyczki zadań wraz z argumentami, których potrzebujemy do uruchomienia funkcji, jak pokazano poniżej.

Wtyczki te można wywoływać za pomocą cy.task(“pluginName”, { ...args }) w dowolnym miejscu w plikach specyfikacji i możesz oczekiwać, że wystąpi taka sama funkcjonalność. Zważywszy, że jeśli użyłeś cy.request() , masz mniej możliwości ponownego użycia, chyba że opakowałeś te wywołania w obiekty strony lub pliki pomocnicze, które mają być importowane wszędzie.

Innym zastrzeżeniem jest to, że ponieważ kod zadania wtyczki ma być uruchamiany na serwerze Node, nie można wywoływać zwykłych poleceń Cypress wewnątrz tych funkcji, takich jak Cypress.env(“apiHost”) lub cy.getCookie('auth_token') . Przekazujesz takie rzeczy, jak ciąg tokena uwierzytelniania lub host interfejsu API zaplecza do obiektu argumentu funkcji wtyczki, oprócz rzeczy wymaganych dla treści żądania, jeśli musi on komunikować się z interfejsem API zaplecza.

Szydzenie żądań sieciowych za pomocą cy.server() i cy.route()

W przypadku testów Cypress wymagających danych, które są trudne do odtworzenia (takich jak odmiany ważnych stanów interfejsu użytkownika na stronie lub radzenie sobie z wolniejszymi wywołaniami interfejsu API), jedną z funkcji Cypress do rozważenia jest blokowanie żądań sieciowych. Działa to dobrze z żądaniami opartymi na XmlHttpRequest (XHR), jeśli używasz waniliowego XMLHttpRequest, biblioteki axios lub jQuery AJAX. Następnie użyjesz cy.server() i cy.route() do nasłuchiwania tras, aby wyszydzić odpowiedzi dla dowolnego stanu. Oto przykład:

Innym przypadkiem użycia jest użycie cy.server() , cy.route() i cy.wait() razem do nasłuchiwania i oczekiwania na zakończenie żądań sieciowych przed wykonaniem kolejnych kroków. Zwykle po załadowaniu strony lub wykonaniu na niej jakiejś akcji, intuicyjna wizualna wskazówka zasygnalizuje, że coś jest gotowe lub gotowe do potwierdzenia i działania. W przypadkach, w których nie masz tak widocznej wskazówki, możesz jawnie poczekać na zakończenie wywołania interfejsu API w ten sposób.

Jeden wielki problem polega na tym, że jeśli używasz pobierania dla żądań sieciowych, nie będziesz w stanie wyszydzić żądań sieciowych ani czekać, aż zakończą się w ten sam sposób. Będziesz potrzebować obejścia polegającego na zastąpieniu normalnego window.fetch wypełniaczem XHR i wykonaniu kilku czynności konfiguracyjnych i porządkowych, zanim testy zostaną uruchomione zgodnie z opisem w tych problemach . Istnieje również experimentalFetchPolyfill właściwość FetchPolyfill od Cypress 4.9.0, która może działać dla Ciebie, ale ogólnie rzecz biorąc, nadal szukamy lepszych metod obsługi blokowania sieci podczas pobierania i używania XHR w naszych aplikacjach bez zepsucia. Począwszy od Cypress 5.1.0, istnieje obiecująca nowa cy.route2() (patrz dokumentacja Cypress ) do eksperymentalnego zamykania w sieci zarówno żądań XHR, jak i pobierania, więc planujemy uaktualnić naszą wersję Cypress i poeksperymentować z nią, aby sprawdzić, czy rozwiązuje nasze problemy.

Polecenia niestandardowe

Podobnie jak w przypadku bibliotek, takich jak WebdriverIO, możesz tworzyć globalne polecenia niestandardowe, które mogą być ponownie użyte i połączone w plikach specyfikacji, takie jak niestandardowe polecenie do obsługi logowania za pośrednictwem interfejsu API przed uruchomieniem przypadków testowych. Po utworzeniu ich w pliku, takim jak support/commands.ts , możesz uzyskać dostęp do funkcji takich jak cy.customCommand() lub cy.login() . Napisanie niestandardowego polecenia do logowania wygląda tak.

O obiektach strony

Obiekt strony to otoczka wokół selektorów i funkcji, która pomaga w interakcji ze stroną. Nie musisz budować obiektów strony, aby pisać testy, ale dobrze jest rozważyć sposoby hermetyzacji zmian w interfejsie użytkownika. Chcesz ułatwić sobie życie pod względem grupowania rzeczy, aby uniknąć aktualizacji selektorów i interakcji w wielu plikach zamiast w jednym miejscu.

Możesz zdefiniować klasę bazową „Page” z typowymi funkcjami, takimi jak open() , dla dziedziczonych klas stron, które mają być udostępniane i rozszerzane. Pochodne klasy stron definiują własne funkcje pobierające dla selektorów i innych funkcji pomocniczych, jednocześnie ponownie wykorzystując funkcjonalność klas bazowych za pomocą wywołań takich jak super.open() , jak pokazano tutaj.

Rezygnacja z uruchamiania kodu po stronie klienta z window.Cypress checks

Kiedy testowaliśmy przepływy z automatycznymi plikami do pobrania, takimi jak CSV, pobieranie często łamało nasze testy Cypress przez zamrożenie przebiegu testowego. Jako kompromis chcieliśmy głównie sprawdzić, czy użytkownik może osiągnąć właściwy stan powodzenia pobierania, a nie pobierać pliku w naszym teście przez dodanie window.Cypress check.

Podczas testów Cypress do przeglądarki zostanie dodana właściwość window.Cypress . W kodzie po stronie klienta możesz sprawdzić, czy w obiekcie window nie ma właściwości Cypress, a następnie przeprowadzić pobieranie w zwykły sposób. Ale jeśli jest uruchamiany w teście Cypress, tak naprawdę nie pobieraj pliku. Skorzystaliśmy również ze sprawdzenia właściwości window.Cypress dla naszych eksperymentów A/B uruchomionych w naszej aplikacji internetowej. Nie chcieliśmy dodawać większej liczby niestabilności i niedeterministycznego zachowania z eksperymentów A/B potencjalnie pokazujących różne doświadczenia naszym użytkownikom testowym, więc najpierw sprawdziliśmy, czy właściwość nie jest obecna przed uruchomieniem logiki eksperymentu, jak podkreślono poniżej.

Radzenie sobie z ramkami iframe

Radzenie sobie z ramkami iframe może być trudne w Cypress, ponieważ nie ma wbudowanej obsługi iframe. Istnieje uruchomiony [problem]( https://github.com/cypress-io/cypress/issues/136 ) wypełniony obejściami do obsługi pojedynczych iframe i zagnieżdżonych iframe, które mogą działać lub nie w zależności od aktualnej wersji Cypress lub element iframe, z którym zamierzasz wchodzić w interakcję. W naszym przypadku użycia potrzebowaliśmy sposobu radzenia sobie z rozliczeniami iframe Zuora w naszym środowisku pomostowym, aby zweryfikować przepływy aktualizacji API Email i Marketing Campaigns API. Nasze testy obejmują wypełnienie przykładowych informacji rozliczeniowych przed zakończeniem uaktualnienia do nowej oferty w naszej aplikacji.

Stworzyliśmy niestandardowe polecenie cy.iframe(iframeSelector) , które hermetyzuje obsługę ramek iframe. Przekazanie selektora do elementu iframe spowoduje sprawdzenie zawartości treści elementu iframe, dopóki nie będzie już puste, a następnie zwróci zawartość treści, aby była połączona z większą liczbą poleceń Cypress, jak pokazano poniżej:

Podczas pracy z TypeScript możesz wpisać swoje niestandardowe polecenie iframe w pliku index.d.ts :

Aby wykonać część naszych testów rozliczeniową, użyliśmy niestandardowego polecenia iframe, aby pobrać zawartość treści iframe Zuora, a następnie wybraliśmy elementy w iframe i bezpośrednio zmieniliśmy ich wartości. Wcześniej mieliśmy problemy z używaniem cy.find(...).type(...) i innych alternatyw, które nie działały, ale na szczęście znaleźliśmy obejście tego problemu, zmieniając wartości danych wejściowych i zaznaczając bezpośrednio za pomocą polecenia invoke, tj cy.get(selector).invoke('val', 'some value') . Będziesz także potrzebować ”chromeWebSecurity”: false w pliku konfiguracyjnym cypress.json , aby ominąć wszelkie błędy związane z różnymi źródłami. Przykładowy fragment jego użycia z selektorami wypełniaczy znajduje się poniżej:

Standaryzacja w środowiskach testowych

Po napisaniu testów za pomocą Cypressa przy użyciu najpopularniejszych asercji, funkcji i podejść, o których wspomniałem wcześniej, jesteśmy w stanie uruchomić testy i przekazać je w jednym środowisku. To świetny pierwszy krok, ale mamy wiele środowisk, w których możemy wdrażać nowy kod i testować nasze zmiany. Każde środowisko ma swój własny zestaw baz danych, serwerów i użytkowników, ale nasze testy Cypress powinny być napisane tylko raz, aby działały z tymi samymi ogólnymi krokami.

Aby uruchomić testy Cypress w wielu środowiskach testowych, takich jak tworzenie, testowanie i pomostowanie, zanim ostatecznie wdrożymy nasze zmiany w środowisku produkcyjnym, musimy skorzystać z możliwości Cypress do dodawania zmiennych środowiskowych i zmiany wartości konfiguracyjnych w celu obsługi tych przypadków użycia.

Aby przeprowadzić testy w różnych środowiskach frontendowych :

Musisz zmienić wartość „baseUrl” dostępną za pośrednictwem Cypress.config(“baseUrl”) , aby dopasować te adresy URL, takie jak https://staging.app.com lub https://testing.app.com . Zmienia to bazowy adres URL dla wszystkich cy.visit(...) , do których dołącza się ich ścieżki. Istnieje wiele sposobów na ustawienie tego, na przykład ustawienie CYPRESS_BASE_URL=<frontend_url> przed uruchomieniem polecenia Cypress lub ustawienie --config baseUrl=<frontend_url> .

Aby uruchomić testy w różnych środowiskach zaplecza :

Musisz znać nazwę hosta interfejsu API, taką jak https://staging.api.com lub https://testing.api.com , aby ustawić zmienną środowiskową, taką jak „apiHost” i uzyskać do niej dostęp za pośrednictwem wywołań, takich jak Cypress.env(“apiHost”) . Będą one używane w cy.request(...) do wysyłania żądań HTTP do określonych ścieżek, takich jak „<apiHost>/some/endpoint” lub przekazywane do wywołań funkcji cy.task(...) jako kolejny argument właściwość, aby wiedzieć, do którego backendu trafić. Te uwierzytelnione wywołania musiałyby również znać token uwierzytelniania, który najprawdopodobniej przechowujesz w localStorage lub plik cookie za pośrednictwem cy.getCookie(“auth_token”) . Upewnij się, że ten token uwierzytelniania zostanie ostatecznie przekazany jako część nagłówka „Authorization” lub w inny sposób w ramach żądania. Istnieje wiele sposobów ustawiania tych zmiennych środowiskowych, na przykład bezpośrednio w pliku cypress.json lub w opcjach wiersza polecenia --env , gdzie można się do nich odnieść w dokumentacji Cypress .

Aby podejść do logowania do różnych użytkowników lub korzystania z różnych metadanych:

Teraz, gdy wiesz, jak obsługiwać wiele adresów URL frontendu i hostów interfejsu API zaplecza, jak radzisz sobie z logowaniem do różnych użytkowników? Jak używać różnych metadanych w zależności od środowiska, takich jak rzeczy związane z domenami, kluczami API i innymi zasobami, które prawdopodobnie będą unikalne w środowiskach testowych?

Zacznijmy od utworzenia kolejnej zmiennej środowiskowej o nazwie „testEnv” z możliwymi wartościami „testing” i „staging”, dzięki czemu można to wykorzystać jako sposób na określenie użytkowników i metadanych środowiska do zastosowania w teście. Używając zmiennej środowiskowej „testEnv”, możesz podejść do tego na kilka sposobów.

Możesz utworzyć oddzielne pliki „staging.json”, „testing.json” i inne środowiskowe pliki JSON w folderze fixtures i zaimportować je do użycia w oparciu o wartość „testEnv”, taką jak cy.fixture(`${testEnv}.json`).then(...) . Jednak nie można dobrze wpisać plików JSON i jest znacznie więcej miejsca na błędy w składni i zapisaniu wszystkich właściwości wymaganych na test. Pliki JSON są również bardziej oddalone od kodu testowego, więc podczas edycji testów musiałbyś zarządzać co najmniej dwoma plikami. Podobne problemy z konserwacją wystąpiłyby, gdyby wszystkie dane testowe środowiska zostały ustawione w zmiennych środowiskowych bezpośrednio w cypress.json i byłoby zbyt wiele do zarządzania w wielu testach.

Alternatywną opcją jest utworzenie obiektu osprzętu testowego w pliku specyfikacji z właściwościami opartymi na testowaniu lub przygotowaniu w celu załadowania użytkownika i metadanych testu dla określonego środowiska. Ponieważ są to obiekty, można również zdefiniować lepszy ogólny typ TypeScript wokół obiektów urządzeń testowych, aby wszystkie pliki specyfikacji mogły być ponownie używane i definiować typy metadanych. Cypress.env(“testEnv”) , aby zobaczyć, w którym środowisku testowym pracujesz, i użyj tej wartości do wyodrębnienia urządzenia testowego odpowiedniego środowiska z całego obiektu urządzenia testowego i użyj tych wartości w teście. Ogólna idea obiektu osprzętu testowego została podsumowana w poniższym fragmencie kodu.

Zastosowanie wartości konfiguracyjnej Cypress „baseUrl”, zmiennej środowiskowej backendu „apiHost” i zmiennej środowiskowej „testEnv” razem pozwala nam mieć testy Cypress, które działają w wielu środowiskach bez dodawania wielu warunków lub oddzielnych przepływów logicznych, jak pokazano poniżej.

Cofnijmy się o krok, aby zobaczyć, jak można nawet tworzyć własne polecenia Cypress, które będą uruchamiane przez npm. Podobne koncepcje można zastosować do przędzy, Makefile i innych skryptów, których możesz używać w swojej aplikacji. Możesz zdefiniować odmiany poleceń „otwórz” i „uruchom”, aby dostosować się do Cypressa „otwórz” GUI i „uruchom” w trybie bezgłowym w różnych środowiskach frontendowych i backendowych w twoim package.json . Możesz także skonfigurować wiele plików JSON dla konfiguracji każdego środowiska, ale dla uproszczenia zobaczysz polecenia z wbudowanymi opcjami i wartościami.

Zauważysz w skryptach package.json , że Twój frontend „baseUrl” waha się od „http://localhost:9001” podczas lokalnego uruchamiania aplikacji do wdrożonego adresu URL aplikacji, takiego jak „ https://staging.app. pl ”. Możesz ustawić zmienne „apiHost” i „testEnv” zaplecza, aby pomóc w wysyłaniu żądań do punktu końcowego zaplecza i ładowaniu określonego obiektu urządzenia testowego. Możesz także utworzyć specjalne polecenia „cicd”, gdy musisz uruchomić testy w kontenerze Dockera z kluczem nagrywania.

Kilka dań na wynos

Jeśli chodzi o wybieranie elementów, interakcję z elementami i potwierdzanie elementów na stronie, możesz zajść całkiem daleko, pisząc wiele testów Cypressa z małą listą poleceń Cypressa, takich jak cy.get() , cy.contains() , .click() , .type .type() , .should('be.visible') .

Istnieją również sposoby na wysyłanie żądań HTTP do backendowego API za pomocą cy.request() , uruchamianie dowolnego kodu na serwerze Node za pomocą cy.task() i eliminowanie żądań sieciowych za pomocą cy.server() i cy.route() . Możesz nawet utworzyć własne niestandardowe polecenie, takie jak cy.login() , aby pomóc Ci zalogować się do użytkownika za pośrednictwem interfejsu API. Wszystkie te rzeczy pomagają zresetować użytkownika do właściwego punktu początkowego przed uruchomieniem testów. Umieść te selektory i funkcje razem w pliku i utworzyłeś obiekty strony wielokrotnego użytku, które możesz wykorzystać w swoich specyfikacjach.

Aby ułatwić pisanie testów, które przechodzą w więcej niż jednym środowisku, skorzystaj ze zmiennych środowiskowych i obiektów zawierających metadane specyficzne dla środowiska.

Pomoże to uruchomić różne zestawy użytkowników z oddzielnymi zasobami danych w specyfikacji Cypress. Oddzielne polecenia Cypress npm, takie jak npm run cypress:open:staging w package.json , załadują odpowiednie wartości zmiennych środowiskowych i uruchomią testy dla wybranego środowiska.

To podsumowuje nasz tysiącmetrowy przegląd pisania testów na Cypress. Mamy nadzieję, że dostarczyło to Państwu praktycznych przykładów i wzorów do zastosowania i udoskonalenia we własnych testach Cypress.

Chcesz dowiedzieć się więcej o testach Cyprysa? Sprawdź następujące zasoby:

  • Co wziąć pod uwagę podczas pisania testów E2E
  • TypeScript Wszystkie rzeczy w twoich testach cyprysowych
  • Radzenie sobie z przepływami wiadomości e-mail w testach cyprysowych
  • Pomysły na konfigurację, organizację i konsolidację testów cyprysowych
  • Integracja testów Cypress z Docker, Buildkite i CICD